The hypothetical case:

HooHaaStore.com is a leading online shopping portal powered by CF. It runs CF on a cluster setup to balance the load amongst the different instances of the server in the cluster. HooHaaStore.com also expects a transparent take over of one server instance from the other in case of a failure in one of the servers. HooHaaStore.com uses a CFC stored in the session scope to keep track of the items purchased by a customer in that session.

Now what would happen if the server serving the shopping request of the customer goes down? The other server instances cannot pickup the shopping order of the customer unless each server has the same instance of the CFC replicated under its session scope.

The servers follow various approaches to session replication. But all of these require the objects stored in the session to be serializable so that the objects can be persisted and replicated.

Scorpio gives a reason to smile in the HooHaaStore.com case as it allows replication of CFCs during session replication in a cluster setup. All this is possible in Scorpio because CFCs are now serializable. From the user’s perspective, CFCs get replicated across the sessions in the cluster during session replication without absolutely any user intervention.

However, since CFCs are serializable, CFC instances can even be stored and retrieved from a file.

Here is the CFML code that first persists a CFC instance into a file and then recreates the instance by reading the CFC back from the file. Note that this is just an additional bit of code to persist CFC instance and is not required for the CFCs to get replicated across sessions. (changed the CFML code below to use CFSCRIPT based on Charlie Arehart’s comment as the code would look better with CFSCRIPT)

Make sure to change the “ajaxui.shoppingcart” cfc instance in the code below to any cfc on your ColdFusion server.

<cfscript>
try
{
//create the cfc that will written to the file
shoppingcartcfc = CreateObject("component","ajaxui.shoppingcart");

//set a variable userid in the this scope of the cfc
shoppingcartcfc.userid = 6;

//create FileOutputStream to point to a file names test.out
fileoutputstream = CreateObject("java","java.io.FileOutputStream");
fileoutputstream.init("test.out");

//create the ObjectOutputStream associated with the above FileOutputStream
objectoutputstream = CreateObject("java","java.io.ObjectOutputStream");
objectoutputstream.init(fileoutputstream);

//write the cfc using the ObjectOutputStream instance
objectoutputstream.writeObject(shoppingcartcfc);

//Now read the cfc from the file
fileinputstream = CreateObject("java","java.io.FileInputStream");
fileinputstream.init("test.out");

objectinputstream = CreateObject("java","java.io.ObjectInputStream");
objectinputstream.init(fileinputstream);

deserializedshoppingcartcfc = objectinputstream.readObject();

//The value of user id from the deserialized cfc will be and should be 6
writeoutput("The value of userid from the deserialized cfc is " &
#deserializedshoppingcartcfc.userid#);
}
catch(Any e)
{
 writeoutput(htmlcodeformat(e.stacktrace));
}
</cfscript>

Making this happen was my first challenge in the ColdFusion team. I will soon come up with a post on ‘how’ it was achieved.

Rakshith

Comments

28 Responses to “CFC Serialization Unplugged”

  1. David R on June 1st, 2007 2:31 am

    Hi Rakshith,

    This is David from India.. I am also working on CF… Great to know that you are a part of CF8 Engineering team… Looking forward to your blogs…

  2. admin on June 1st, 2007 3:49 am

    Thanks David! Good to know that you are working on CF. By the way, do you have the ColdFusion 8 Beta installed? If not, you can get it here.

    Rakshith

  3. Charlie Arehart on June 2nd, 2007 7:10 am

    Rakshith, welcome to the blogosphere, and thanks for offering another voice out of Adobe engineering.

    About your entry, though, I’m confused by a couple of things. First, you don’t show any code working with CFCs. Indeed, all you’re showing is writing a string to a file using java objects. You could have done the same with CFFILE. Did you mean to show something more. Did you mean to show more, or just offer this as an example to those who might want to see how “serialization” in java could work from CFML?

    More to the point of the case study and title of the entry though, wouldn’t it instead be the desire (and function) that serialization of the CFCs would happen automatically, by the J2EE engine (JRun or otherwise), when it did whatever it did to replicate sessions across cluster members? Isn’t it just that such replication simply failed before 8 if the session had a CFC, and that now it will work?

    I ask this in humility, with only some knowledge of these things. If you or anyone else can clarify, I’d appreciate it.

    Your code example implies that a manual effort that must be and even if it was changed to really work with CFCs, it would beg the question of when and how one would trigger such code in the event of an attempt at session replication. It just doesn’t seem to me that manual serialization is the solution to be highlighting. Or have I got it wrong?

    Again, I do welcome your blogging and am sure others will benefit. You’ll find the CF community very open and welcoming–but they also aren’t afraid to ask questions–and share tips with each other. :-) Indeed, I have a couple other unrelated thoughts that I’ll share in another comment.

  4. Charlie Arehart on June 2nd, 2007 7:16 am

    Since you mention in an earlier entry that you’re new to CF, I want to also recommend that you check out CFSCRIPT if you’ve not already. Your code above would look a lot nicer to many (and indeed more acceptable to those who are bugged by tags) if you changed it to use CFSCRIPT.

    Indeed, if you come from a java background, you may appreciate how much more closely this looks to how you might do such code in Java (thought it’s definitely CFML, with the use of CreateObject instead of New, and writeoutput to show output to the browser). I’ve also added an htmlcodeformat function, which you could use in your example as it is as well, to make the displayed stacktrace more attractive.

    Here’s how it could appear (don’t know how it will look when Wordpress receives it. There should be an opening and closing CFSCRIPT tag below, which may be stripped, and each statement should be on its own with tabs for indentation):

    try {
    // create the object that will written to the file
    stringobject = CreateObject(”java”,”java.lang.String”);
    stringobject.init(”test string”);

    // create FileOutputStream to point to a file names test.out
    fileoutputstream = CreateObject(”java”,”java.io.FileOutputStream”);
    fileoutputstream.init(”test.out”);

    // create the ObjectOutputStream associated with the above FileOutputStream
    objectoutputstream = CreateObject(”java”,”java.io.ObjectOutputStream”);
    objectoutputstream.init(fileoutputstream);

    // write the java string object using the ObjectOutputStream instance
    objectoutputstream.writeObject(stringobject);

    } catch (Any e) {
    writeoutput(htmlcodeformat(e.stacktrace));
    }

    Again, just trying to share a tip with you and others who may read this.

  5. Charlie Arehart on June 2nd, 2007 7:24 am

    Well bummer. It not only removed the cfscript and indentation, but it also changed the double quotes to character entries (#8221), so one can’t copy/paste it and expect it to work. I won’t try to repost it, but if you have any suggestions about how I might get it to work correctly, I’m happy to help (or if you want to put the corrected code in the entry and point to it as a comment, that may work best, if you think it useful.)

    Finally, I meant to add, for those who may run your code and wonder where the test.out gets created, on a server edition of CF, it would be in a directory like C:\cfusionmx7\runtime\bin.

    In a JRun/multi-instance deployment, it would be in a directory like c:\jrun4\bin.

    Hope that’s helpful.

  6. admin on June 4th, 2007 5:14 am

    First of all, thanks for all the inputs Charlie.

    I have changed my post based on your comments. Most of your comments definitely made sense.

    Yeah, CFCs get replicated in Scorpio during session replication without the user having to do anything specifically for the CFC replication.

    Now that CFCs are serializable, I have a bit of CFML code that persists and reads a CFC instance from a file. I have changed the CFML code to use CFSCRIPT as the code looks a lot nicer with CFSCRIPT.

    I cannot use CFFILE in my bit of code. This is because I am interested in writing objects here to the file which CFFILe does not allow. Or if there is a way to, do share it with me.

    Yes replication simply failed before CF8 if the session had a CFC. It now works in CF8.

    I did not change the code you posted to escape the tags as I have changed my post accordingly.

    I appreciate all your inputs. Keep them coming!

  7. Eric on June 20th, 2007 6:25 pm

    I am trying to deserialize a cfc to a form field and the serialize it back to a cfc during form processing. Do you know if this is possible? It seems that you would be able to write the object to a string rather than an object and read the string on the processing page but I have been unable to get it working. Any suggestions?

  8. admin on June 22nd, 2007 12:23 am

    I must say, a very intuitive way of using CFC serialization. I am trying to understand the use case here. I am curious to know why do you want take advantage of CFC serialization here.

    At the first glance, this is seems possible to me. Unless the binary data in the form field gets corrupted when it reaches the server over HTTP, I don’t see a problem here. Will it be possible for you to share your code here?

  9. Lomeos on October 9th, 2007 8:50 am

    reconstructing an object seems to fail when there’s an array variable in it. ColdFusion gives a ‘coldfusion.runtime.Array’ error.

    ‘java.lang.ClassNotFoundException: coldfusion.runtime.Array’ according to the stack trace.

    Writing goes fine. Any idea why this is?

    Cheers

  10. Lomeos on October 9th, 2007 10:46 am

    The same thing applies to queries. Apparently only strings, structs and objects are valid during the readObject().

    Cheers

  11. Rakshith on October 17th, 2007 11:50 pm

    Lomeos,
    Your observation is right. Unfortunately cfc serialization fails with Array, Date, DateTime or Query objects within the CFC. We are aware of this issue and will come up with a fix soon.

    Thanks for pointing it out!

  12. AJ on November 30th, 2007 9:24 am

    Rakshith: any ETA on that fix?

    Possible Workaround
    We’ve run into the same issue with arrays/queries in our CFCs, preliminary testing shows that they can be put in a CFC function if the variable is declared as a var at the top of the function (of course they won’t get serialized then).

    Our workaround was to change all the arrays in the CFCs variables scope to lists and to stuff query objects into structs.

    To avoid changing the interface of the CFC you can convert between types. The caveat is that the unsupported types need to be declared as var.

    For example:

    … stuff list into array

    We also have some cfquery tags in some functions. In order for those to work the name of the cfquery is declared as:

    YOUR QUERY HERE

    This of course is only really feasible if you have only a few existing CFCs with this issue.
    So bottom line, you can’t serialize the types mentioned above, but it appears you can still use them in the CFC if they are declared var.
    Hope it helps if you can’t wait for the fix.

  13. AJ on November 30th, 2007 9:28 am

    well, it took out my example tags, hope the post still makes sense. Mmmmh, maybe if I leave off the tag delimiters?

    example:

    cfset var returnArr = ArrayNew(1)
    …stuff list into array
    cfreturn returnArr

    query example:

    cfset var qryName = “”
    cfquery name=”qryName” datasource=”dsn”
    YOUR QUERY HERE
    /cfquery

  14. Brook on December 2nd, 2007 7:27 pm

    Did this get fixed? Can serialization work with arrays/queries etc?

  15. Rakshith on December 2nd, 2007 11:28 pm

    Brook,
    We have a bug logged in our system on this and will try to fix the issue soon. That is the update on the issue for the moment. Will let you know once its fixed.

  16. Amir on January 23rd, 2008 5:02 am

    So is this still a problem?. I was looking fwd to clustering up a few instances on CF8 (on the same box) but we use session vars everywhere and this could be a show stopper :-(

  17. Jon Hirschi on March 3rd, 2008 12:43 am

    Rakshith,

    It looks like there is still an issue with dates not being deserialized properly when included in the “this” scope, do you know if a fix is imminent on this? Also, are there any other data types that you are aware of that can’t be deserialized from a coldfusion cfc?

    thanks!

  18. Chris on March 3rd, 2008 2:45 am

    Is there any progress on fixing this bug?

  19. Ian Bale on April 2nd, 2008 2:23 am

    Same problem with Arrays – they serialise just fine, but throw a similar error to the dates when you try to deserialise.

    Like everyone else here, I am rather keen to make use of this functionality, so would be very grateful if you can offer a likely date when this might be fixed…?

    Thanks

    Ian

  20. Rakshith on April 2nd, 2008 4:02 am

    Guys,
    I cannot commit on a likely date of fix. But I can assure that this on our list of bugs and will be looked into soon.

  21. Ian Bale on April 4th, 2008 2:50 am

    I see a fix didn’t make it into Updater 1, although bug number 70495 did look like it might be the right one…

    Do you have a bug tracking number for this bug? That way those of us with access to Adobe bug tracking can keep an eye on developments that way.

  22. Don Q on August 2nd, 2008 12:22 am

    Hate to ask, hoping maybe I missed the bug fix or real workaround, but… Any updates?

  23. Rakshith on August 4th, 2008 10:35 pm

    @ Ian : The fix is not in the updater. The bug number for this issue is 70580.

    @Don : There is no fix out yet. But we know that is an issue and is logged in our database. We will look into it soon.

  24. Jim Crews on May 13th, 2009 1:46 pm

    This still isn’t fixed, is it? Is there a hotfix or something that I am missing? Do you know of any other ways to serialize ColdFusion components? My initial thought was to use WDDX, but CFML2WDDX doesn’t support CFCs.

    I actually used the above to create a ComponentConverter object with serialize and deserialize methods before discovering the Array nastiness.

    :-(

    – Jim C.

  25. Jim Crews on May 13th, 2009 2:43 pm

    I found this CFC for creating XML objects from CFCs (and vice versa)in the meantime. It DOES work with Arrays, etc:

    http://www.celticinternet.com/blog2/post.cfm/cfc-serialisation-with-coldfusion-8

  26. ColdFusion 8: Hotfix for CFC Serialization released : The Sprint on June 29th, 2009 12:53 am

    [...] CFC serialization is a feature that came out in ColdFusion 8. With this feature it is now possible to serialize a cfc, i.e. it is possible to write an instance of a cfc to an outputstream. In simple words, it is possible to write cfc instances to a file and read them back. CFCs stored in the session now get replicated across the servers in the cluster as well because of CFC Serialization. [...]

  27. Rakshith on June 29th, 2009 1:13 am

    Guys, good news! The hotfix for the cfc serialization issue has been released. Check my post now!

  28. Rakshith on August 23rd, 2009 10:33 pm

    @CFUser – If the book really says that, then that statement in the book is wrong. I am guessing that this would be corrected in the recent version of the book.

    Session replication with cfcs should work for you on ColdFusion 8. Can you give out more details on how you are trying to get this working?

Leave a Reply