Igniters,

In some cases there is necessity to control a type of object that is being inserted into a cache. Presently this kind of check is accomplished at compile time only relying on Java Generics. However it doesn't prevent us from connecting to a cluster using a non-generic instance of a cache and put any kind of data in it.
This may be not a harmful intention but rather a silly developer mistake.

I see the following options here.

1) First CacheInterceptor based approach.
Specify a unique interceptor per cache setting expected typeName/typeId to it at construction time and the interceptor will validate object type in onBeforePut() method.
Disadvantages:
- cache interceptor have to be created for every cache;
- cache interceptor class has to be located in servers classpath. It means that we won't be able to start a new cache with its interceptor later.

2)  Second CacheInterceptor based approach.
A generic cache interceptor can be created. It will be populated with a map of cacheName->typeName values at initialization time and validation may look like below

@CacheNameResource String cacheName;

public Object onBeforePut(Cache.Entry<String,BinaryObject> entry,BinaryObject  
newVal) {
    if (typeId ==null) {
        synchronized (cachesTypes) {
            if (typeId ==null) {
                String allowedType =cachesTypes.get(cacheName);

                if (allowedType ==null) {
                    typeId =0;

                    throw new IgniteException("No type for cache name:" 
+cacheName);
                }

                typeId = Ignition.ignite().binary().typeId(allowedType);
            }
        }
    }

    if (newVal.type().typeId() !=typeId)
        throw new IgniteException("Invalid object type [validType=" +typeId +", 
wrongType=" + newVal.type().typeId());

    return newVal;
}

However if we want to start a new cache then we won't be able to add a new entry to "cacheTypes" map. 3) MutableConfiguration.setTypes(Class<K> keyType, Class<V> valueType) based approach According to the spec

Implementations may further perform type checking on mutative cache operations * and throw a {@link ClassCastException} if these checks fail.

If we see that value type is BinaryObject (this can be a case if there BinaryObject is not going to be deserialized because no real class exists for it) then we can take its typeName/typeId and compare it with the same parameters at the time instances of BinaryObjects will be put to cache using cache.put(). So, every time cache.put()/putAll() are called we can check type on client nodes before sending values to servers. In case of CacheEntryProcessors servers will double-check an entry type after the entry processor does its job. I prefer the latest approach. Any thoughts on this? -- Denis

Reply via email to