Memcached and caching JPA entities

760 views
Skip to first unread message

nobullet

unread,
Jul 26, 2010, 5:57:20 AM7/26/10
to play-framework
Does anybody have some recommendations and rules about using relations
in JPA entities and caching these entities with Memcached?

I have entity User and City:

class User extends play.db.jpa.Model implements Serializable {

@ManyToOne(fetch = FetchType.LAZY)
private City city;

}

City is very simple: id and name (with Hibernate's @Index annotation).
When using Memcached to cache entities that has User reference I see
exception in logs:

Could not deserialize
java.lang.ClassCastException: cannot assign instance of
org.hibernate.proxy.pojo.javassist.SerializableProxy to field
models.user.User.city of type models.City in instance of
models.user.User
at java.io.ObjectStreamClass
$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2032)
at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:
1212)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:
1953)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:
1871)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:
1753)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:
1947)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:
1871)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:
1753)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at java.util.LinkedList.readObject(LinkedList.java:964)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:
974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:
1849)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:
1753)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:
1947)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:
1871)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:
1753)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at java.util.ArrayList.readObject(ArrayList.java:593)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:
974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:
1849)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:
1753)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at play.cache.MemcachedImpl$1.deserialize(MemcachedImpl.java:43)
at
net.spy.memcached.transcoders.SerializingTranscoder.decode(SerializingTranscoder.java:
66)
at net.spy.memcached.transcoders.TranscodeService
$1.call(TranscodeService.java:36)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at net.spy.memcached.transcoders.TranscodeService
$Task.run(TranscodeService.java:83)
at java.util.concurrent.ThreadPoolExecutor
$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor
$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:637)

Do I need to skip using FetchType.LAZY with Memcached?
No problems with Ehcache (when Memcached is disabled).

GrailsDeveloper

unread,
Jul 26, 2010, 7:09:14 AM7/26/10
to play-framework
Hi,
not exactly and answer to your question, but I wouldn't put a JPA-
Object into memcache. I guess it's cheaper to read it again from
database.
But it's only a design decision.

Furthermore I assume you must detach the object from the hibernate
session.

Regards
Niels

nobullet

unread,
Jul 26, 2010, 8:32:59 AM7/26/10
to play-framework
Ehcache works on one JVM, Memcached server can be moved to separate
machine (it's possible to use Play cluster if to follow stateless
architecture).
Play examples advises to use Memcached: http://www.playframework.org/documentation/1.0.3/cache

The possible workaround is described here: https://jira.jboss.org/browse/JBAS-3952
:
You may define your relation as EAGER when possible...

But it's not perfect - joins, big datasets between jvm and database...
Big overhead.

It's possible not to use relation:
store Long city_id instead of City, and have setter and getter:

public void setCity(City city) {
this.city_id = city.getId();
}

public City getCity() {
return City.findById(this.city_id);
}

It works (even multiple calls to getCity() will return object from
Hibernate's session) but it is ugly.

Is there any nicer way?

On Jul 26, 2:09 pm, GrailsDeveloper <opensourc...@googlemail.com>
wrote:
Reply all
Reply to author
Forward
0 new messages