-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 
Author Message
 Post subject: Enhancement to serialization
PostPosted: Sun Jan 23, 2005 4:24 am 
Newbie

Joined: Sun Jan 23, 2005 3:48 am
Posts: 4
Gavin requested I post this here:

During serialization (writing to an ObjectOutputStream), rather then serialize an uninstantiated object reference as a proxy, I would like to instantiate the proxy target (call getImplementation()) during calls to writeReplace() so I will never get proxies written to the stream.

Currently the class LazyInitializer intercepts writeReplace() and replaces the proxy with the object returned by a call to serializableProxy(). Currently, the only way to change the serialization behavior is to change the object returned by that call as you cannot change or subclass the invoke method in LazyInitializer (it's marked final).

In order to modify serializableProxy() I had to replace EntityPersister, CGLIBProxyFactory, and CGLIBLazyInitializer due to code dependencies. Then specify the new EntityPersister in my mapping files.

It would be nice, instead of doing all that and basically using serializableProxy() for a purpose other then originally intended, if there could be a flag in the mapping file (or some other way) to cause LazyInitializer to call getImplementation() rather then serializableProxy() to select the object to write to the stream.

Cheers
Steve


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 23, 2005 4:40 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
You realize what an incredibly bad idea this is?

ie, you will end up fetching your entire database during serialization, and all one-row-at-a-time, using piecemeal little SQL SELECTs.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 23, 2005 5:07 am 
Newbie

Joined: Sun Jan 23, 2005 3:48 am
Posts: 4
gavin wrote:
You realize what an incredibly bad idea this is?

ie, you will end up fetching your entire database during serialization, and all one-row-at-a-time, using piecemeal little SQL SELECTs.


No, I won't. For two reasons.

Firstly, I do not have proxy collections. Only many-to-one references will be instantiated, so the database will only be followed at most to the top of the chain (a parent object).

Secondly, the stream itself knows when to stop following the chain for the dataset being transfered.

My solution is already implemented and working fine (no it doesn't retrieve the entire database), I am simply asking for a feature that would be useful in general and in particular make it so I don't have to worry about maintaining a bunch of code I had to create just to work around the impossibility of extending CGLIBLazyInitializer.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 25, 2005 1:43 am 
Newbie

Joined: Sun Jan 23, 2005 3:48 am
Posts: 4
I figured out a way to do this now, it's working great. It would have been a lot easier, gavin, if you had tried to help rather then just blow me off. But it's all fine now in any case.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 25, 2005 3:30 am 
Beginner
Beginner

Joined: Tue Aug 10, 2004 8:59 am
Posts: 47
I have the exact same problem. I am trying to use getImplementation() to get a non-proxied bean which I can serialize and send to a system which does not know anything about hibernate. This seems not to be possible - I get a class cast exception saying the target system does not know class SerializableProxy. I do not have the option of including hibernate in the target system, yet I need to send this persistent bean over the network.

If you found a way to do this without hibernate altering the expected serialization process I would really be interested in hearing some hints about how to do this.


Thanks

Randahl


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 29, 2005 12:19 pm 
Newbie

Joined: Sun Jan 23, 2005 3:48 am
Posts: 4
When you serialize a hibernate proxy it replaces the proxy with an instance of SerializableProxy.

What I do is subclass ObjectOutputStream to enable replaceObject and then replace the SerializableProxy with either null or an instanciated instance depending on my need.

eventually getting to a method like this one:

Code:
  public Object replaceObject(SerializableProxy source) {
    try {
      Class clazz = (Class) classGetter.get(source);
      if( entities.contains(clazz) ) {
        Serializable id = (Serializable) idGetter.get(source);
        return ((SessionImplementor) SessionFactoryUtils.getSession(sessionFactory, false)).immediateLoad(clazz, id);
      }
    } catch( Exception e ) {
      throw new ApplicationException("Error loading needed instance");
    };
    return null;
  }


This relies on knowing the internals of SerializableProxy and so can change after upgrading Hibernate, but what can you do... ;)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 29, 2005 1:13 pm 
Beginner
Beginner

Joined: Tue Aug 10, 2004 8:59 am
Posts: 47
Thanks for the tip, but I just don't get why it has to be so extremely difficult to convert a Hibernate graph of beans to a regular Java graph of beans. It is so obvious that many people could use this. Say for instance you wish to generate some XML, there are APIs which convert beans to XML, only you need the bottom most classes to be the real beans, not the hibernate proxies.

This is something I would REALLY like to see improved in hibernate.

Randahl


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 17, 2005 11:56 am 
Beginner
Beginner

Joined: Mon Sep 15, 2003 12:41 pm
Posts: 21
I have the same problem, except I do not perform serialization -- yet. I basically have an interceptor (Spring) which gets rid of all proxies in the returned object graph. My graphs are small (I intentionally planned them this way), so I do not care about the number of queries I could perform during the process.

But SerializableProxy is really gets into the way!
I badly want an easy way to convert it into the actual object.

And I don't understand as well why the task of externationalization of Hibernate-loaded objects is so troublesome?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 17, 2005 12:39 pm 
Beginner
Beginner

Joined: Mon Sep 15, 2003 12:41 pm
Posts: 21
Well, I have to admit that I'm wrong. There is a simple way to do that.
I just had to set all "lazy" attributes in mappings to "false".
No more work required.

Still, it would be good to have an ability to externalize object tree programmatically -- in cases when not every's request results are to be sent over the wire. For local results I would use proxies, and for external clients -- called externalize().


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 18, 2005 7:07 am 
Beginner
Beginner

Joined: Tue Aug 10, 2004 8:59 am
Posts: 47
Setting lazy to false degrades performance - it would be better if you could run with lazy=true and still convert to proxy free graphs on the fly.

Randahl


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jun 18, 2005 8:52 pm 
Beginner
Beginner

Joined: Mon Sep 15, 2003 12:41 pm
Posts: 21
Quote:
Setting lazy to false degrades performance - it would be better if you could run with lazy=true and still convert to proxy free graphs on the fly.


Sure. But in my case all data are almost immediately sent over the wire, so the performance is the same or better than lazy+externationalization.

But as soon as I'll be doing something more complex on the server side, and send only a subset of objects to the client, the performance would degrade significantly...

Really, I don't see a point in not having a facility to get rid of proxies in a given object tree. What's wrong with this approach?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.