Compound Theory

v2.0

Categories

  1. Transfer
  2. ColdFusion
  3. JRuby
  4. Java
  5. ColdSpring
  6. Squabble
  7. JavaLoader
  8. ColdDoc
  9. 2ddu
  10. AsyncHTTP
  11. OO Analysis and Design
  12. Flex
  13. Railo
  14. XML / XSL
  15. Hibernate
  16. ColdFusion Builder
  17. Fall
  18. Ubuntu
  19. XHTML / CSS
  20. Eclipse
  21. Git
  22. Oracle Database
  23. Usability / UI Design
  24. webDU
  25. cf.Objective()
  26. LWJGL
  27. cf.Objective(ANZ)
  28. Captcha
  29. MAX
  30. Melbourne CFUG
  31. Martial Arts
  32. Random Things
  33. Conduit

Recent Posts

Projects

Recent Comments

31 August 2009 12:43 PM 2 Comments

JavaLoader 1.0 Alpha is Released!

JavaLoader 1.0 is a project I've been talking about off and on for the past 6 months or so, and I'm very happy to announce that a release version is now complete.

There are several key new features to JavaLoader 1.0,

Dynamic Compilation

Now if you are working with JavaLoader, you don't have to bundle your Java code into a jar to load.  You can simply specify to JavaLoader which directories are your source directories, and JavaLoader will compile and load them on the fly for you!  JavaLoader will also check to see if your source code has changed, and re-compile it as necessary! 

For example, if I wanted to compile and load a HelloWorld.java (that has a simple 'Hello World' method) in my ./src directory, I could do:

javaloader = createObject("component", "javaloader.JavaLoader").init(sourceDirectories=[expandPath('./src')]);

And then create my HelloWord object as per normal:

<cfset helloWorld = javaloader.create("HelloWorld").init()>
<cfoutput>#helloWorld.hello()#</cfoutput>

No more ANT tasks, no more export to .jars, JavaLoader handles the compilation and deployment of your Java code for you.

ColdFusion Component Dynamic Proxy

For those of you who are not aware of what a Dynamic Proxy in Java is, it is essentially an Object that can mimic an object that implements a given set of Interfaces.  The method invocations against that object are intercepted, and you can essentially do whatever you like with them.

In JavaLoader 1.0, I've written a Dynamic Proxy that you are able to wrap around a CFC, and thereby make Java Objects think they are interacting with a native Java object, but are in fact, talking to your CFC.  When a Java Object calls a method on the Dynamic Proxy, it is passed through and invoke directly on the CFC transparent to your Java layer.

For example, the java.lang.Thread Java object can take an instance of the interface java.lang.Runnable in its constructor argument.  Using JavaLoader's Dynamic Proxy, we can pass it what it thinks is an instance of the Runnable Interface, but is in actuality a ColdFusion Component like so:

//give us access to the CFCDynamicProxy
CFCDynamicProxy = javaloaderloader.create("com.compoundtheory.coldfusion.cfc.CFCDynamicProxy");

//create my Runner CFC
myRunner = createObject("component", "MyRunner").init();

//wrap it in a Dynamic Proxy, that implements Runnable
runnerProxy = CFCDynamicProxy.createInstance(myRunner, ["java.lang.Runnable"]);

//pass it to the Thread and call run()
thread = createObject("java", "java.lang.Thread").init(runnerProxy);
thread.run();

...and suddenly we have true seamless communication from Java to ColdFusion components.

This is actually something I wish I had written three years ago.  It would have radically altered how I would have written a lot of software.

Spring Integration

A natural progression from the Dynamic Proxy, was to implement a Custom Schema in Spring, so that you could instantiate and dependency inject your ColdFusion components with your Java Objects inside Spring itself.

Initialising Spring with JavaLoader is covered in the documentation, but to give you a quick taste, once we have Spring running, we can include a CFC in our spring.xml with:

<coldfusion:cfc id="message"
        script-source="file://home/www/model/Message.cfc"
        script-interfaces="com.IMessage"
        />


Where script-source is the absolute path to the CFC you want to instantiate, and script-interfaces are the Java interfaces that your dynamic proxy will implement, and your CFC has mirrored inside it.

This Component then gets treated like a normal Spring bean, so it can be autowired, injected, aop'd and all the usual functionality that a Spring bean has access to.

There are some downsides to implementing Components inside Spring, so be sure to check out the documentation for more details.

Read More

For more details, have a read of the extended documentation, and have a look at the examples provided in the download.

Since this has become a far larger project than its original inception, I've done away with the Riaforge Forum, and have started a new javaloader-dev google group for support and discussion of JavaLoader and Java and ColdFusion integration.

While I'm very confident in the code that I have written for JavaLoader 1.0, I decided to call it an Alpha, simply because it has only really been tested by me and my Unit Tests.  Knowing from experience that users of Open Source Software have a tendency to use and abuse libraries far above and beyond what the author had ever originally dreamed led me to decide to call it Alpha until the community has really had a good change to play with it.

Please download JavaLoader 1.0, take it for a spin, sign up for the mailing list, and if you find any problems please do let me know.
26 August 2009 02:46 PM 3 Comments

Getting UTF-8 and MySQL to work with ColdFusion 9 ORM

A question I've seen show up quite often in Hibernate forums is 'How do I get Hibernate to generate UTF-8 Compliant Tables and/or columns when it generates my database tables when using mySQL?'

It's actually, quite easy to do, but often (myself included), people end up looking deep into Hibernate for some mysterious setting.

In reality, it's just a question of setting up your database correctly.  The first thing you need to do is set your database to use UTF-8 character coding as its default, like so, when creating it:

create database my_new_database default CHARACTER SET = utf8 default COLLATE = utf8_general_ci;

This will ensure all tables that are created by ColdFusion's ORM are created with a UTF-8 character set.

That being said, I have seen issues when data is being sent up to MySQL in UTF-8 form getting corrupted.  To ensure the database drivers use the correct character set as well we add useUnicode=true&characterEncoding=UTF-8 to our MySQL connection string in the ColdFusion Admin under the datasource's Advanced Settings.

There you go! UTF-8 support in mySQL with ColdFusion ORM!

17 August 2009 07:03 PM 7 Comments

Overloading ORM Implicit Get and Set Methods

This is something I just ran into with ColdFusion 9's ORM implementation, that thankfully Rupesh got back to me very fast on, otherwise, I probably would have been confused for quite a while.

I needed to overwrite a get and set value in a CFC I was creating.  We will say for arguments sake I was hashing a password on a User object (even though I was doing something completely different), like so:

component output="false" persistent="true"
{
    property name="userid" fieldtype="id" ormtype="int" generator="identity" hint="primary key";
    property name="name" type="string" notnull="true" length="200" hint="The user's name";
    property name="password" type="string" length="200" hint="The user's password";

    public void function setPassword(String password)
    {
        instance.password = hash(arguments.password);
    }

    public String function getPassword()
    {
        return instance.password;
    }
}

This is how I would usually have written my Components, storing my data in variables.instance, so they wouldn't overlap with any of the data stored in my variables scope.

What I couldn't understand was, my password would keep getting stored in my database as NULL, even though I had explicitly set it.

Thankfully Rupesh explained that when the ColdFusion ORM retrieves and populates data in an ORM managed CFC, it directly accesses the variables scope in the CFC.  So in the above instance, the ORM was finding no data for the password, and interpreting that to mean that I wanted to insert that as NULL into my database.

Therefore,  to get my code to work was to store my data in the variables scope, like so:

component output="false" persistent="true"
{
    property name="userid" fieldtype="id" ormtype="int" generator="identity" hint="primary key";
    property name="name" type="string" notnull="true" length="200" hint="The user's name";
    property name="password" type="string" length="200" hint="The user's password";

    public void function setPassword(String password)
    {
        variables.password = hash(arguments.password);
    }

    public String function getPassword()
    {
        return variables.password;
    }
}

This way the ORM can find exactly what it is looking for, and I can manipulate my data the way I want.

The fact that the ORM integration works this way is actually a very good thing, as it means that my password above doesn't get hash'd over and over again, but it is something we all should be aware of when you want to overwrite the implicit get and set functions that get generated by <cfproperty> declarations.

04 August 2009 07:27 AM 12 Comments

ColdFusion 9 ORM - Explaining Hibernate Object State

In the previous two articles, we started the discussion of Hibernate Sessions and how they related to the ColdFusion 9 ORM.  We noted the fact that a Hibernate Session keeps track of what objects it loads, and can therefore update it when it realises that the object has changed.  The question then posses itself - if a Hibernate Session has closed, which happens at the end of every ColdFusion request, what happens to the objects that it was managing?

Going forward, I'm going to reuse the Musician model I used in the Introducing ORM in Adobe ColdFusion 9 beta Adobe DevNet article, for which the updated code samples can be found here.

The very short version for those who don't wish to look at the code, is a model in which we have a Musician, who has a name, and an age, and he/she also has a many-to-many relationship to an array of Instruments, which they can play.

As far as Hibernate is concerned, there are three different states for any Object that it interacts with.

Transient

An Object/Entity (you could use either word) is Transient, if it has just been created with a createObject() or new operator, but has yet to be saved with the EntitySave() method.

Obviously, if transient objects are not persisted via EntitySave(), then they never get stored in the database, and will eventually be garbage collected.

For example, our musician john below is a transient object:

 

<cfscript>
    import com.*;
   
    //this is transient
    john = new Musician("Transient John");
</cfscript>

Since john is never saved, it will always be transient.

Persistent

A Persistent object is one that has either come from, or has been saved in the database, within the scope of the current Hibernate Session (which is an important point to note).

For example, we can make our musician john below persistent, by:

<cfscript>
    import com.*;
   
    //join is transient
    john = new Musician("Transient John");
    
    john.setAge(47);

    //john is now persistent   
    EntitySave(john);
</cfscript>

Therefore, since john was inserted into the database, he is persistet.

By the same token, if we retrieve an object through the ORM, it is also persistent:

<cfscript>
    //larry's ID is 2

    //larry is also persistent
    larry = EntityLoad("Musician", 2, true);
    
    //As larry is persistent, we can change his age, which will be reflected in the database
    larry.setAge(19);
</cfscript>

Since larry was retrieved from the database, he is also persistent.

Detached

Detached objects are ones that used to be persistent, but the Hibernate Session has closed. Detached objects were one of the biggest things for me to wrap my head around when starting with Hibernate, and can cause a few really tricky errors to occur.

To explain detached a little better, we can go through a scenario that will causes them, as I think this is something that a lot of ColdFusion developers are going to end up running in to.

Let's have a new musician, called Tim, and time is going to have 2 instruments that he plays, the Flute and Piano.

We are going to grab Tim out of the database, and then put him in our ColdFusion Session scope, so we can keep track of him from request to request.

<cfscript>
    tim = EntityLoad("Musician", 2, true);
    
    session.musician = tim;    
</cfscript>

For this request, Tim will be persistent, however, on the next request, Tim is now detached, as the Hibernate Session will have closed at the end of the previous request.

Therefore, if I do this:

<cfscript>
    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

You will see the following (not well written) error:

failed to lazily initialize a collection of role: Musician.instruments, no session or session was closed

If you are running ColdFusion via the console, you will also see something similar to:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: Musician.instruments, no session or session was closed


What does this error even mean? 

First of all, we should remember that the collection of Instruments our Musician can play are lazy loaded. This means they aren't actually loaded from the database into the object until you actually request them.

The important thing to note here, is that lazy loading with Hibernate can only occur if the Hibernate Session that the object was originally loaded from is still open.  To put it another way, if the Hibernate Session has closed, then Hibernate has no record of what the object was doing, and therefore can't do any lazy loading.

In the above example, since the previous ColdFusion request ended, the Hibernate Session has closed, and if you attempt to access a relationship that is set to lazy load, and has yet to be loaded, this error occurs.

Its should be noted that singular properties are not lazy loaded - therefore, if you are just grabbing a property on an object that is detached, no error will be thrown.

What can we do to mitigate this issue? There are a few options, one of which is, to simply retrieve the object all over again, like so:

<cfscript>
    session.musician = EntityLoad("Musician", session.musician.getMusicianID(), true);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">
Or, like so:
<cfscript>
    session.musician = entityLoadByExample(session.musician, true);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

As then the object we are dealing with is considered persistent, as it is attached to the currently open Hibernate Session.  This tends to be the easiest of the options when dealing with detached objects.

Another interesting way of making our detached object persistent is like so:

<cfscript>
    EntitySave(session.musician);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

This may look strange, but what is actually happening when you call EntitySave(), is that it calls the Hibernate method saveOrUpdate()

A quick version of what saveOrUpdate() does is -

Therefore in the example above, the data stored in session.musician will be saved again to the database, and since session.musician is now deemed persistent, we can successfully do lazy loading of the instruments.

However, if a situation like this would occur:

<cfscript>
    musicianTwo = EntityLoad("Musician", session.musician.getMusicianID(), true);

    EntitySave(session.musician);
</cfscript>

We get the following error:

a different object with the same identifier value was already associated with the session: [Musician#2]

Since Hibernate deems the persistent object that is currently connected to the Hibernate Session much more important than the detached object, which makes sense, as the persistent object has the most up to date version of the data stored in the database.

Generally speaking, if you at all can, try and avoid having detached objects in your application, as this is generally a Good Thing™, and will allow you to avoid some pretty decent headaches as you develop with CF9 ORM.  Strategies such as storing IDs in the ColdFusion Session and having an API to return a new Object by that ID on request is often a good way to go, rather than storing the Entity itself in the ColdFusion Session.  That being said, if your architecture means that you have to have detached objects this series should be enough to give you a basic grounding the concepts of object state, and how to manage it.

If you want to learn more about managing Hibernate Object States (and there is far more to it than I have written here), you can read more about this in the Hibernate documentation, but this should hopefully have given you a decent enough overview to avoid some possible pitfalls when handling persistence with ColdFusion 9's ORM integration.