[OSB, Coherence] OSB Result Cache Invalidation from C++ Client

原文はこちら。
https://blogs.oracle.com/jaylee/entry/osb_result_cache_invalidation_from

[訳注]
この方法はサポートされていません。参考にされるのは結構ですが、あくまでも自己責任でお願いします。

最近お客様よりOSB結果キャッシュのデータを無効化したい、との問い合わせを受けました。データを無効かするキーを作成する方法はないので、取り得る最善の方策はフィルタを使うことです。コードスニペットを以下に記載します。
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;
    }

}
ここで一つ問題があります。それは、ビジネスサービスのどの結果を無効化すべきかわからないということです。2個のビジネスサービスがたまたま同じトークンを持っている場合、これは両方のトークンを削除することになって望ましいことではありません。また、インデックスが所定の位置にないため、キャッシュサイズが巨大である場合、パフォーマンスの課題も考えられます。現在のところ、Keyのクラスを作成する方法はわかっていません。独力でやってみようとしましたが、どういうわけか、作成したものとOSBが生成したものが異なっていました。そのため、最後には自作のResultCacheロジックを作成し、この目的を達成したのです。

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 = "null";
            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();
        }
    }
}


これで、キャッシュを無効化することができます。
String::View deleteKey = key;
String::View vsCacheName = "dist-test";
NamedCache::Handle hCache = CacheFactory::getCache(vsCacheName);
hCache->remove(deleteKey);
近い将来OSBのキャッシュ無効化機能が追加されると信じています。

0 件のコメント:

コメントを投稿