playframework / play-plugins

CachePlugin
444 stars 161 forks source link

Redis cache always uses Serializable/ObjectOutputStream #88

Open aellerton opened 11 years ago

aellerton commented 11 years ago

I am using the play redis cache to store Strings (JSON, actually). I'd like those strings to be useful for non-Java applications but noticed that the cache always stores them as below:

redis 127.0.0.1:6379> get somekeyhere "oos-rO0ABXQAgHsidHlwZSI6ImN1c3RvbWVyIiwidXNlcl91dWlkIjoiOGMxMzVjMDgtMjkzZi00NjQ3LTgyND98BjIiwiZW1haWwiOiJzYWxseUBjdXN0b21lci50ZXN0IiwiZGlzcGxheU5hbWUiOiJTYWxseSBCdXllciJ9"

Serializing direct to the cache (i.e. bypassing the redis plugin) works for strings no problem.

The code at https://github.com/typesafehub/play-plugins/blob/master/redis/src/main/scala/com/typesafe/plugin/RedisPlugin.scala shows the reason why: the type test is applied to Serializable first, so the test for String is never applied:

   if (value.getClass.isInstanceOf[Serializable]) {
      oos = new ObjectOutputStream(baos)
      oos.writeObject(value)
      oos.flush()
   } else if (value.getClass.isInstanceOf[String]) {
      dos = new DataOutputStream(baos)   // <-- NEVER GETS HERE!
      dos.writeUTF(value.asInstanceOf[String])
      prefix = "string"

The solution is to put the Serializable test at the end, after String, Int, Long, Boolean.

salehsed commented 11 years ago

Does it have any relation with getting objects out of cache ?

"play.api.cache.Cache.getAsUser"

warn] application - could not deserialize key ex:java.lang.ClassNotFoundException: models.User java.lang.ClassNotFoundException: models.User

aellerton commented 11 years ago

My version of play (2.1.3) doesn't have a getAsUser method. It has getAs[T] which is quite a lot more useful, I think.

In any case, the error you list is completely unrelated to the issue I've logged. Your issue is related to there being no models.User class found at runtime in your app.

The issue I've logged here is that serialization /does/ work with String (and objects), but with String it should write it directly as a string, not encode with an ObjectOutputStream.

salehsed commented 11 years ago

Thanks for the comment , Raised an issue for getAs https://github.com/typesafehub/play-plugins/issues/89

jroper commented 11 years ago

A pull request that fixes this will most certainly be accepted.

aellerton commented 11 years ago

No worries, I'll submit one to you soon. ..

peter-fu commented 10 years ago

The solution is to put the Serializable test at the end, after String, Int, Long, Boolean.

Agree.

Also, a data migration guide should be provided after this is fixed, because some Cache data are external and might be stored in redis via play-redis plugin.

sunnykaka commented 9 years ago

This is still going on in 2.3.1, any solutions?