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