I'm using Hazelcast (JAVA, version 3.7.5) in a scenario with 2 members. The first member delegates a task to the second member through an IExecutorService
. After some processing, the second member tries to send back an unserializable response.
As it's not possible to send back a response, the second member prints the stacktrace related to the HazelcastSerializationException
.
As no response arrives, the first member throws an OperationTimeoutException
when the operation-heartbeat-timeout is reached.
Currently, when the IExecutorService fails at parsing the Callable result, it prints a stacktrace (on callee side). Let say I have a simple caller :
private Future<Object> startFlow() {
//This throws an OperationTimeoutException
return hazelcastInstance.getExecutorService("myExecutor").submit(myRunnable);
}
Which calls a simple callee :
@Override
public Object call() throws Exception {
//The object returned is not serializable, therefore an HazelcastSerializationException is thrown
return service.execute();
}
The callee prints a stacktrace after it failed to parse the response (see end of post).
In my case, it's not possible to know what kind of object the service
might return, and it's not possible to trust the service
to send back serializable objects.
I would like to be able to know the reason of the timeout on the caller-side.
After some search, I found that no configuration/API is available to intercept exceptions thrown by an IExecutorService when it fails to serialize a response.
So I tried to see if it would be possible to check if an object was parseable by Hazelcast, again without success.
Any ideas ?
Thank you
The stacktrace printed by the callee will be looking like this :
Exception in thread "hz._hzInstance_1_dev.cached.thread-1" com.hazelcast.nio.serialization.HazelcastSerializationException: Failed to serialize 'com.hazelcast.spi.impl.operationservice.impl.responses.NormalResponse'
at com.hazelcast.internal.serialization.impl.SerializationUtil.handleSerializeException(SerializationUtil.java:73)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:143)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:124)
at com.hazelcast.spi.impl.operationservice.impl.OperationServiceImpl.send(OperationServiceImpl.java:427)
at com.hazelcast.spi.impl.operationservice.impl.RemoteInvocationResponseHandler.sendResponse(RemoteInvocationResponseHandler.java:51)
at com.hazelcast.spi.Operation.sendResponse(Operation.java:291)
at com.hazelcast.executor.impl.DistributedExecutorService$CallableProcessor.sendResponse(DistributedExecutorService.java:269)
at com.hazelcast.executor.impl.DistributedExecutorService$CallableProcessor.run(DistributedExecutorService.java:253)
at com.hazelcast.util.executor.CachedExecutorServiceDelegate$Worker.run(CachedExecutorServiceDelegate.java:212)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at com.hazelcast.util.executor.HazelcastManagedThread.executeRun(HazelcastManagedThread.java:76)
at com.hazelcast.util.executor.HazelcastManagedThread.run(HazelcastManagedThread.java:92)
Caused by: com.hazelcast.nio.serialization.HazelcastSerializationException: Failed to serialize 'com.myomain.UnserialiableObject'
at com.hazelcast.internal.serialization.impl.SerializationUtil.handleSerializeException(SerializationUtil.java:73)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.writeObject(AbstractSerializationService.java:236)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeObject(ByteArrayObjectDataOutput.java:371)
at com.hazelcast.spi.impl.operationservice.impl.responses.NormalResponse.writeData(NormalResponse.java:91)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:189)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:54)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.write(StreamSerializerAdapter.java:43)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:140)
... 12 more
Caused by: com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable serializer for class com.myomain.UnserialiableObject
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.serializerFor(AbstractSerializationService.java:469)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.writeObject(AbstractSerializationService.java:232)
... 18 more
EDIT (SOLUTION)
So I ended up registering a global serializer, that would simply send an Exception whenever it's called. Something like this :
public class GlobalSerializerException implements StreamSerializer<Object> {
@Override
public void write(ObjectDataOutput out, Object object) throws IOException {
String objectInfo;
if(object == null){
objectInfo = "Object was null.";
}else{
objectInfo = String.format("Object of class %s and printed as String gives %s", object.getClass().getCanonicalName(), object.toString());
}
objectInfo = "Hazelcast was unable to serialize an object. " + objectInfo;
out.writeUTF(objectInfo);
}
@Override
public Object read(ObjectDataInput in) throws IOException {
String message = in.readUTF();
HazelcastSerializationException hazelcastSerializationException = new HazelcastSerializationException(message);
return hazelcastSerializationException;
}
@Override
public int getTypeId() {
return 63426;
}
@Override
public void destroy() {
}
}