Getting following error while inserting data in Ignite cache? - java

This error is occurred while using JsonObject(GSON Library) in cache value if I used String instead of JsonObject then operation perform successfully.
Error which I have get while inserting data in cache:
javax.cache.CacheException: class org.apache.ignite.transactions.TransactionRollbackException: Transaction has been rolled back: 9557fcfb061-00000000-078a-a446-0000-000000000001
at org.apache.ignite.internal.processors.cache.GridCacheUtils.convertToCacheException(GridCacheUtils.java:1287)
at org.apache.ignite.internal.processors.cache.IgniteCacheProxyImpl.cacheException(IgniteCacheProxyImpl.java:1648)
at org.apache.ignite.internal.processors.cache.IgniteCacheProxyImpl.put(IgniteCacheProxyImpl.java:1008)
at org.apache.ignite.internal.processors.cache.GatewayProtectedCacheProxy.put(GatewayProtectedCacheProxy.java:872)
at com.clouzer.databaseoperation.DataBaseOperation.getAllUSerGson(DataBaseOperation.java:527)
at com.mstorm.ignition.gson.LoginCacheOperation.createLoginCache(LoginCacheOperation.java:38)
at com.mstorm.ignition.gson.IgniteCacheCreator.createCaches(IgniteCacheCreator.java:30)
at com.mstorm.ignition.gson.IgniteServer.main(IgniteServer.java:102)
Caused by: class org.apache.ignite.transactions.TransactionRollbackException: Transaction has been rolled back: 9557fcfb061-00000000-078a-a446-0000-000000000001
at org.apache.ignite.internal.util.IgniteUtils$11.apply(IgniteUtils.java:860)
at org.apache.ignite.internal.util.IgniteUtils$11.apply(IgniteUtils.java:858)
... 8 more
Caused by: class org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException: Transaction has been rolled back: 9557fcfb061-00000000-078a-a446-0000-000000000001
at org.apache.ignite.internal.processors.cache.GridCacheAdapter.syncOp(GridCacheAdapter.java:4054)
at org.apache.ignite.internal.processors.cache.GridCacheAdapter.put0(GridCacheAdapter.java:2340)
at org.apache.ignite.internal.processors.cache.GridCacheAdapter.put(GridCacheAdapter.java:2321)
at org.apache.ignite.internal.processors.cache.GridCacheAdapter.put(GridCacheAdapter.java:2298)
at org.apache.ignite.internal.processors.cache.IgniteCacheProxyImpl.put(IgniteCacheProxyImpl.java:1005)
... 5 more
Caused by: class org.apache.ignite.IgniteCheckedException: Can not set final com.google.gson.internal.LinkedTreeMap field com.google.gson.JsonObject.members to java.util.LinkedHashMap
at org.apache.ignite.internal.util.IgniteUtils.cast(IgniteUtils.java:7252)
at org.apache.ignite.internal.util.future.GridFutureAdapter.resolve(GridFutureAdapter.java:259)
at org.apache.ignite.internal.util.future.GridFutureAdapter.get0(GridFutureAdapter.java:171)
at org.apache.ignite.internal.util.future.GridFutureAdapter.get(GridFutureAdapter.java:140)
at org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal$10.applyx(GridNearTxLocal.java:2396)
at org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal$10.applyx(GridNearTxLocal.java:2392)
at org.apache.ignite.internal.util.lang.IgniteClosureX.apply(IgniteClosureX.java:38)
at org.apache.ignite.internal.util.future.GridFutureChainListener.applyCallback(GridFutureChainListener.java:78)
at org.apache.ignite.internal.util.future.GridFutureChainListener.apply(GridFutureChainListener.java:70)
at org.apache.ignite.internal.util.future.GridFutureChainListener.apply(GridFutureChainListener.java:30)
at org.apache.ignite.internal.util.future.GridFutureAdapter.notifyListener(GridFutureAdapter.java:383)
at org.apache.ignite.internal.util.future.GridFutureAdapter.listen(GridFutureAdapter.java:353)
at org.apache.ignite.internal.util.future.GridFutureAdapter$ChainFuture.<init>(GridFutureAdapter.java:572)
at org.apache.ignite.internal.util.future.GridFutureAdapter.chain(GridFutureAdapter.java:358)
at org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal.optimisticPutFuture(GridNearTxLocal.java:2391)
at org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal.putAsync0(GridNearTxLocal.java:622)
at org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal.putAsync(GridNearTxLocal.java:385)
at org.apache.ignite.internal.processors.cache.GridCacheAdapter$22.op(GridCacheAdapter.java:2342)
at org.apache.ignite.internal.processors.cache.GridCacheAdapter$22.op(GridCacheAdapter.java:2340)
at org.apache.ignite.internal.processors.cache.GridCacheAdapter.syncOp(GridCacheAdapter.java:4040)
... 9 more
Cache Configuration:
CacheConfiguration<String, JsonObject> cacheConfig = new CacheConfiguration<>();
cacheConfig.setName("CACHE_NAME");
cacheConfig.setReadThrough(true);
cacheConfig.setBackups(2);
cacheConfig.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
cacheConfig.setWriteThrough(true);
cacheConfig.setCacheStoreFactory(FactoryBuilder.factoryOf(ObjectLoader.class));
IgniteCache<String, JsonObject> cache = ignite.getOrCreateCache(cacheConfig);
Operations:
1.create JsonObject (use GSON library)
2.set cache loader to the given cache which used for persistent store
3.insert data into the cache from ignite client-side
4.observe the issue

The problem is that JsonObject has members field of type LinkedTreeMap, and Ignite BinaryMarshaller, which is default one, deserializes it into a LinkedHashMap for some reason.
To avoid it you can use a different marshaller, for example, OptimizedMarshaller.
UPD:
Turns out, if you configure OptimizedMarshaller, then only puts and gets from cache will work fine. But if you try to get(...) some field of the deserialized representation of JsonObject, for example, then JVM will crash.
The reason is that LinkedTreeMap has the following writeReplace() method:
private Object writeReplace() throws ObjectStreamException {
return new LinkedHashMap(this);
}
So, if you serialize it, and after that deserialize, then you will get an instance of LinkedHashMap instead of LinkedTreeMap. So, BinaryMarshaller is doing nothing wrong.
Summary:
Looks like you shouldn't put JsonObjects into cache. It doesn't implement Serializable, so the authors didn't think about serializing it. I think, you will have to replace JsonObject with JSON strings.

Related

How to Serialize an object of rx.Single returned by a function?

I am using Spring Framework and trying to cache the results returned by a method using #Cacheable annotation.
The method returns an object of rx.Single class. I am getting following error when trying to cache the results,
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [rx.Single]
How can I proceed to cache the results? or
How can I serialize an object of rx.Single class?
The answer is: you can't.
You can create your own class, which will hold all required information and make it Serializable.

Getting "declares multiple JSON fields named" error when serializing with GSON

Type type = new TypeToken<HashMap<String , MovieDb>>() {}.getType();
gson.fromJson(json, type); //ERROR HERE !!!
When I convert from Json to the hashmap object it works fine without minifying enabled. But when minify is enabled it gives me the following error at this line:
java.lang.IllegalArgumentException: class a.a.a.a.b declares multiple JSON fields named a
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:172)
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:102)
at com.google.b.e.a(Gson.java:458)
at com.google.b.b.a.b.a(CollectionTypeAdapterFactory.java:53)
at com.google.b.e.a(Gson.java:458)
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:117)
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:166)
at com.google.b.b.a.i.a(ReflectiveTypeAdapterFactory.java:102)
at com.google.b.e.a(Gson.java:458)
at com.google.b.b.a.g.a(MapTypeAdapterFactory.java:126)
at com.google.b.e.a(Gson.java:458)
at com.google.b.e.a(Gson.java:926)
at com.google.b.e.a(Gson.java:892)
at com.google.b.e.a(Gson.java:841)
at com.techy.nateshmbhat.moviego.i.onPreExecute(MovieInterface.java:180)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:648)
at android.os.AsyncTask.execute(AsyncTask.java:595)
at com.techy.nateshmbhat.moviego.i.b(MovieInterface.java:101)
at com.techy.nateshmbhat.moviego.a.a(Activity_InTheaterMovies.java:55)
Your error is most propably because you minify two fields to a same name a. Something like:
#SerializedName("a")
Long veryLongFieldName;
#SerializedName("a")
Long anotherVeryLongFieldName;
Note that these can be either in the same class or if using inheritance it is enough that they are in the same inheritance tree. Gson can not assign two values to one minimized field name a.
It could of course also be that you have minimized some field to a name that is already reserved by some other unminimized field.
I've faced this issue when I had context property/variable in the model class

Spring session, recover from "local class incompatible" after deployments

Spring session stores serialized objects in my database. The problem is, sometimes my code changes. Sometimes my objects change. This is normal. However, I get errors like this:
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [byte[]] to type [java.lang.Object] for value '{-84, ..., 112}'; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.InvalidClassException: com.mysite.MyClass; local class incompatible: stream classdesc serialVersionUID = 1432849980928799324, local class serialVersionUID = 8454085305026634675
I get this error by invoking a Spring Boot endpoint with HttpSession as an argument, such as this one:
#GetMapping("/stuff")
public #ResponseBody MyClass getStuff(HttpSession session) {
try {
Object myObject = session.getAttribute("MyClass");
if (myObject != null && myObject instanceof MyClass) {
return (MyClass) myObject;
} else {
return null;
}
} catch (Exception e) {
logger.warn("Invalid session data", e);
return null;
}
}
However, because the exception is thrown before the method gets invoked, I am not able to recover from this normal, expected error.
As a workaround, I am forced to delete the entire session table each deployment, even though most of the objects are still compatible!
To be clear, the solution is NOT to add a serialVersionUuid. Because the objects really do change in non-compatible ways from one deployment to the next. This is not a serialization question. This is a Spring Session error recovery question.
My question is: How can I gracefully recover from these issues?
You did not provide details but I assume you are using Spring's JDBC session implementation enabled by #EnableJdbcHttpSession?
In this case you can take a look at JdbcHttpSessionConfiguration and particularly at setSpringSessionConversionService and setConversionService. I believe if you provide your own implementation (you can see example at createConversionServiceWithBeanClassLoader) then you should be able to catch deserialization error and return empty session.
I think all you need is derive MyNotFailingSessionDeserializer from DeserializingConverter, override convert method, catch SerializationFailedException and return null or empty session (not sure if either works).
Then you create your conversion service like createConversionServiceWithBeanClassLoader does but use your MyNotFailingSessionDeserializer instead of DeserializingConverter

Limit Jackson Serialization/Deserialization Depth for all the class

I have tried CustomJSONSerializer from
Suppress wrapper object when serializing Java object into JSON using Jackson.
But getting following exception:
com.fasterxml.jackson.databind.JsonMappingException: object is not an instance of declaring class (through reference chain: com.fasterxml.jackson.databind.type.SimpleType["test"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:197)
at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:183)
I want to serialize entity Like
Entity A
Entity A.Parent
Entity A.Parent.Parent
I got this error too when switching from jackson 2.1.5 to 2.2.0 (or 2.2.1), try downgrading jackson to 2.1.5? Assume it's due to stricter checks in 2.2, but haven't figured out yet how to correct it.

Play-Framework: Causing a 'IllegalArgumentException occured

The error I get is 'IllegalArgumentException occured' Can not set java.util.ArrayList field mi.types.ListOfObjects.objects to java.util.LinkedList
I'm doing the following...
ListOfObjects objects = li.getUsersObjects();
which works perfectly fine normally, however when I do the exact same call with the exact same code inside of Play it doesn't. I'm calling it in my Security Controller inside the authenticate() function. There's a case where the users objects are gotten from an external server. That's when this call is made. It works fine without Play and I'm pretty sure worked before I put it in the Security Controller. Why would putting it here cause such a problem?
EDIT
ListOfObjects is a custom object which contains some values.. It's located inside li which is a library I'm importing. It looks something like this...
public class ListOfObjects {
private ArrayList<Object> objects;
public ArrayList<Object> getObjects(){
return objects;
}
}
getUserObjects simply returns the objects for that user. It grabs them from a server and then uses gson to parse them. However I'm getting the above error when I attempt to.
EDIT2
No matter what I do my type for getUserObjects seems to always be returning as a LinkedList even though it's an ArrayList object. I've tried calling getObjects() directly and there's no change.
EDIT 3
getUserObjects is defined as...
Gson gson = new Gson();
ListOfObjects objects = gson.fromJson(r.getBody(), ListOfObjects.class);
StackTrace...
where r.getBody() is the JSON response from the server
Execution exception (In /app/controllers/Security.java around line 57)
IllegalArgumentException occured : Can not set java.util.ArrayList field lm.types.ListOfObjects.objects to java.util.LinkedList
play.exceptions.JavaExecutionException: Can not set java.util.ArrayList field lm.types.ListOfObjects.objects to java.util.LinkedList
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:227)
at Invocation.HTTP Request(Play!)
Caused by: java.lang.IllegalArgumentException: Can not set java.util.ArrayList field lm.types.ListOfObjects.objects to java.util.LinkedList
at com.google.gson.FieldAttributes.set(FieldAttributes.java:188)
at com.google.gson.JsonObjectDeserializationVisitor.visitFieldUsingCustomHandler(JsonObjectDeserializationVisitor.java:118)
at com.google.gson.ObjectNavigator.navigateClassFields(ObjectNavigator.java:158)
at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:131)
at com.google.gson.JsonDeserializationContextDefault.fromJsonObject(JsonDeserializationContextDefault.java:73)
at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:51)
at com.google.gson.Gson.fromJson(Gson.java:568)
at com.google.gson.Gson.fromJson(Gson.java:515)
at com.google.gson.Gson.fromJson(Gson.java:484)
at com.google.gson.Gson.fromJson(Gson.java:434)
at com.google.gson.Gson.fromJson(Gson.java:406)
at lm.lib.LMethods.getUsersObjects(LMethods.java:165)
at controllers.Security.createNewUser(Security.java:57)
at controllers.Security.authenticate(Security.java:36)
at play.utils.Java.invokeStaticOrParent(Java.java:159)
at controllers.Secure$Security.invoke(Secure.java:193)
at controllers.Secure$Security.access$0(Secure.java:184)
at controllers.Secure.authenticate(Secure.java:64)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:540)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:498)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:474)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:469)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:157)
... 1 more
Debugger failed to attach: recv failed during handshake: Connection reset by peer
Exception message clearly says that Gson deserializes list as LinkedList, whereas field of your ListOfObjects is declared as ArrayList.
The general rule to avoid this kind of problems is not to use implementation classes in field declarations. Use List instead:
public class ListOfObjects {
private List<Object> objects;
...
}

Categories