calling methods on deserialized objects

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View

Hello Perl Specialists,

i'm struggling with a weird problem ....

I have stored an "object tree" in a CGI::Session. I want to make the whole
object model persistent, when the page has finished rendering and restore
all the stuff when the page is loaded by a new request. So far so good: The
object structure seems to be serialized correct. When looking at the
structure with Data::Dumper before and after the
serialization/deserialization step, I can see no difference. Even the
blessing and backpointers in the structure are maintained. But anyway an
error occurs when trying to call methods on the deserialzed objects.


I have a "restored" object like:

my $page = $session->param;

now I want to iterate through the child controls and call a method on them:

foreach my $controlName (keys (%}))
  my $childControl = $page->->{$controlName };
  $childControl->load(); # i've checked that $childControl is a valid
blessed reference at this point!

The "$childControl->load();" statement causes the following error:

"can't locate object method "load" via package SMDplus::Web::Controls::Form

As the error also shows, perl is well aware of the class where the load
method is implemented. Unfortunately it says that the package doesn't
contain the "load" method (which is not the case).

I can achieve what I want by transforming the statement

$childControl->load(); # generates error


my $class = ref($childControl);
eval("$class\:\:load($childControl)"); # works fine

Since I don't want to use eval for several reasons, I am looking for a way
to make the "intuitive syntax" work. I should say that i'm using
"inheritance" as well....  I'm very confused about this behaviour and also
have the bad feeling, that I didn't understand some fundamentals of perl
"objects" :-(.

Can anybody please enlight me? This problem drives me mad by the time ...

kind regards

Re: calling methods on deserialized objects

On 08/25/2006 03:32 PM,  wrote:
Quoted text here. Click to load it

I've haven't used CGI::Session, but I don't think it'll work
for two reasons: 1) serialization and deserialization breaks
the internal connection between hashes and their associated
classes, and 2) after deserialization, objects referred to by
references may be in different locations.

I have three bits of advice: 1) bless the hashes back into
their respective classes after deserialization, 2) use custom
serialization and deserialization methods to reconstruct the
object tree for each request, and 3) make sure the objects'
package (class) files are loaded before deserializing.

This post is a WAG so forgive me if I'm totally off the wall.

The ref() function returns a string of text and, by itself, is
no indication that the internal bytecode that connects a hash
reference to a class is still there.

Re: calling methods on deserialized objects

thanks for your reply ...

Quoted text here. Click to load it
What "internal connection" are you refering to? As far as i know, an object
is nothing more than a blessed hash reference!? So the "connection" between
hashref (object) and package (class) is the blessing (the packagename stored
with the hashref), or am I missing something here? If there IS actually
something more, this would explain the behaviour ...

Quoted text here. Click to load it
This is not a problem (at least in my case). The serialized structure looks
good (I had a look at the session text file), references are replaced by
their serialized target, no memory address pointers inside ...

Quoted text here. Click to load it
they do have the correct class! (since ref($hashref) returns the correct

Quoted text here. Click to load it
would be an option ...
but I still hope to find a way to use the default session deserializer.

Quoted text here. Click to load it
This is something I thought of too ...
I will check, if this helps. But anyway: if the packages would not have been
loaded, the "eval-way" of calling the method could not have worked, could

Quoted text here. Click to load it
I don't know what WAG stands for, but i forgive you in any case and thank
you for your time :-)

Quoted text here. Click to load it
If there is some "internal bytecode" could you please give me a link to an
explanation? Cause I didn't find anything like this in my perl book.

kind regards

Re: calling methods on deserialized objects

On 08/25/2006 06:35 PM, Michael Kper wrote:
Quoted text here. Click to load it

Again, my entire previous post was a Wild A$$ Guess (WAG);
take it with some grains of salt.

I imagined that invisible Perl bytecode establishes the
connection between a hash reference and it's class. I was
wrong, because I tried it with Data::Dumper and FreezeThaw,
and it worked.

Note, I didn't use CGI::Session but instead stored the data in
the __DATA__ section.

Quoted text here. Click to load it

It should work, even without re-blessing.

Quoted text here. Click to load it

At least in PHP, storing objects in sessions doesn't work if
the class definitions aren't loaded when the session data is
loaded by the interpreter (AFAIR). Although Perl is a
completely different language, the problem is (probably) the
same. How can you associate an object's data with a class if
the class' definition isn't loaded?

Quoted text here. Click to load it

I can't test your program because you didn't post one.

Why don't you post a minimal but complete Perl script that
demonstrates your problem, so you can get some responses that
are better than WAGs :-)

Re: calling methods on deserialized objects

I found workaround which works for me ...
I have implemented a method "revive" on the WebControl BaseClass and each
derived class. Because the hashRef is correctly blessed after
deserialization, the method doesn't need any other arguments. It simply
clones the object and "repairs" references to other objects. It returns a
reference to the new object. So, with one call of:

$newRoot = $rootObject->revive();

I can restore recursively the whole object tree after deserialisation.
Methods can be called again on each object in the cloned object tree.

Site Timeline