Archive for the 'cfml' Category

CF Groovy 1.0RC (With Hibernate!)

I've just released 1.0RC of CF Groovy, including Hibernate support.  You can download it, or view the demo app.  The download includes both the demo and the runtime engine.

The big new feature is Hibernate support, of course.  Here are a couple snippets from the demo app.  First, the entity class:

package com.barneyb

import javax.persistence.*

@Entity
class User extends AbstractEntity {

    String firstName
    String lastName
    String email

    @Column(unique = true)
    String username
}

Then the engine setup (in code here, ColdSpring would be better):

<cfset application.cfhibernate = createObject("component", "HibernatePlugin").init() />
<cfset application.cfhibernate.setEntityPath(
    getDirectoryFromPath(getCurrentTemplatePath()) & "entities"
) />
<cfset application.cfhibernate.setColdFusionDsn("cfgroovydemo") />
<cfset application.cfhibernate.setAnnotatedClasses(listToArray("com.barneyb.User")) />
<cfset application.cfgroovy = createObject("component", "cfgroovy").init() />
<cfset application.cfgroovy.addPlugin(application.cfhibernate) />

Finally, doing some persistence operations:

<cfset request.sess = application.cfhibernate.getSessionForRequest() />
<g:script>
import com.barneyb.*

variables.user = new User([
    firstName: attributes.firstName,
    lastName: attributes.lastName,
    username: attributes.username,
    email: attributes.email
])
request.sess.save(variables.user)
request.sess.flush()
</g:script>
<cfset userList = request.sess.createQuery(
    "from User order by lastName, firstName, username"
).list() />

As you can see, very minimal fuss to do some pretty powerful things.  This only scratches the surface of what Hibernate can do; the full power of the tool is available (custom annotations, the full XML mapping capabilities, caching, etc.).

Another significant change is that all non-inline Groovy is precompiled into Java classes and loaded dynamically.  This gives you compiler checks on your Groovy code and engine startup, more helpful message for code errors, and some performance improvements.

Finally, as illustrated above, the <g:setPath> tag has been superceded by an explicitly managed CF Groovy runtime.  This gives you complete control over the lifecycle of the engine, which lets you target performance in production and development speed in development.  You can still use <g:setPath> instead of managing the runtime yourself, but that should be considered a deprecated practice.

CF Groovy w/ Hibernate Sample App

I want to put together a little sample app leveraging CF Groovy and it's Hibernate integration, but I don't know what. From a high level, the architecture will look like this:

  • CFML for the view layer (the HTML templates)
  • CFML for the web controller (probably FB3Lite)
  • CFML and Groovy for the service layer (ColdSpring-managed CFC's with Groovy delegation where appropriate)
  • Groovy w/ Hibernate for the data layer

The question is what the application should do. The default choice of a simple blog engine is, well, boring. I considered implementing the BlogCFC API as a drop-in replacement for BlogCFC backed by Hibernate, but that means mapping the legacy schema, which I don't really want to get into for a simple demo.

My next choice is a simple survey application, since that at least has the potential to be real-world useful. It's also sufficiently simple and would provide appropriate illustration of the concepts I need to demo. The data model for survey construction is simple, but it gets a bit nastier with response storage, and I'd like to avoid too much nasty.

I've implemented a basic timeclock as a sample app a few times (CFML, Spring+Hibernate, Grails) as well, but there's a lot of "application" in there, compared to the amount of persistence, which is what I want to be highlighting.

So, my all-knowing readers, what simple app do you want me to implement? Preferably something that will be useful to people, either as it is, or as a starting point for building a richer version of what I produce. I've just about got the Hibernate APIs nailed down, but I've got a couple more hours on that task.  I'm thinking that Wednesday night I'll pick something and start coding, so speak up (in the comments) with what you want to see.

Fun with Classloading in Java

With my CF Groovy project, I've been doing a lot of Java coding of late. It's all been written in CFML, but it's mostly Java code in CFML syntax. As an aside, doing that sucks. CFML is horrible for writing anything more than the simplest Java code. But on to the topic at hand….

To this point in my career, basically all of the Java code I've written has been application code. Most of the CFML, JavaScript, and ActionScript I write is also application code, but I've contributed significantly to Fusebox and built a number of micro-frameworks in all three languages. However, none of that touches on the stuff I've done in the past couple weeks. The primary source of my issues getting Groovy and Hibernate to play together was classloading.

Unlike Grails (GORM, really), any of the various examples on the web, and I'm guessing Joe Rinehart's Hiberailooving project, three of the inviolate framework objectives were zero dependency on an IDE beyond text editing, no manual compilation, and no container restarts. Obviously, Hibernate provides a set of IDE tooling that can be brought to bear, but I'm talking about just the CF integration portion. I want to be productive with emacs and a web browser.

This presented a number of issues with classloading, because Groovy can only be loaded by the GroovyClassLoader (and subclasses). Basically this forced my hand to using compiled Groovy code, and ensuring it and Hibernate are loaded by the same ClassLoader. No GroovyClassLoader at all.

Now all that's well and good, but you have to be a bit careful, because two of the goals where no manual compilation and no container restarts. Doing compilation from CF is fairly simple (instantiate FileSystemCompiler and call 'main' with the right args), though again, getting all the right stuff on the classpath in the right order proved a nightmare. This is further complicated by the while JEE classloader situation, which isn't straightforward at all.

The details of this intricate dance completely escaped me for a week and a half. Then one night, while lying in bed, it all clicked together (thank you, Heather, for going to England). The solutions seem fairly obvious now, but they took a lot of fussing and fighting to deduce. I'd never even instantiated a ClassLoader before, aside from a couple one-off URLClassLoaders in CFML to lazy-load some JARs. Now I've got stacks of ClassLoaders, in some places two or three deep.

After my initial post-epiphany implementation was complete, I realized I can do some streamlining, but that's for after the release. I think I can even remove the need to drop the Groovy JAR in your /WEB-INF/lib folder, without adding any code complexity or runtime overhead, which would a nice bonus for ease of deployment. I.e., unzip the engine, write an entity, save it to the DB. No JARs, no restart the container, nothing.

It's been a very interesting (and pleasurable) experience, since it's so different from my day job of banging out boring little presentation apps all day. I've learned a lot, and even just the past few days of thinking about how other Java apps/frameworks work, I've realized how applicable that knowledge really is.

CF Groovy Redux

I just got through significantly revamping CF Groovy so that it's CFC based, instead of all in the custom tags.  The custom tags remain, but now you can create and manage a CF Groovy runtime instance manually, rather than letting the tags do it for you.  This will greatly assist in production performance as the tag-based version recreated everything each request.  It's also a prerequisite for Hibernate support, as Hibernate spinup is non-trivial and needs to be avoided unless needed, even in development.

These changes are still in the Hibernate branch in Subversion, not the main trunk.  I don't plan on moving the new code back to the trunk until the Hibernate integration is complete.

CF Groovy Takes a Nap

After close to two weeks of struggling, I finally managed to deploy pure source to a CFML runtime (Railo, in this case), and get Groovy entities in and out of the database with Hibernate.  No compliation, no IDE, no development-mode server, just my Groovy source along with a hacked up CF Groovy.  This is very exciting for me, because while Groovy is cool and all, CF's dynamic nature has become a must have.

I don't have source to download yet, just a horribly hacky proof of concept, but here's what the user of the "framework" does.  First, create your entity:

package com.barneyb
import javax.persistence.*

@Entity
class Person {

  @Id
  @GeneratedValue
  Long id
  Long version
  String name
  Date dob

  def getAgeInSeconds() {
    (new Date().getTime() - dob.getTime()) / 1000
  }

  def getAgeInDays() {
    ageInSeconds / 86400
  }

  def getAgeInYears() {
    ageInDays / 365.249
  }

  String toString() {
    "$name is $ageInYears years ($ageInDays days) old"
  }

}

That's the same class as my initial CF Groovy demo used, except with the of JPA annotations added.  Because I'm binding to Hibernate, you can use any Hibernate-supported annotations, but I opted to stick with vanilla JPA.  Now we need our hibernate.cfg.xml, which is totally stock:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

  <session-factory>

    <property name="current_session_context_class">thread</property>
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <property name="show_sql">true</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/dbname</property>
    <property name="hibernate.connection.username">username</property>
    <property name="hibernate.connection.password">password</property>
    <property name="hibernate.hbm2ddl.auto">update</property>

    <mapping class="com.barneyb.Person" />

  </session-factory>

</hibernate-configuration>

You could also map your classes manually with XML, if you wanted, but for the sake of simplicitly, I've done it all with annotations.  You'll also notice the database connection information embedded directly in the file. This is far from ideal.  I'm hoping to extract it from a CFML DSN, but that might only be possible on Adobe ColdFusion (via the Admin API).  The last thing is the test script:

<g:script>
  import java.text.SimpleDateFormat

  import org.hibernate.*
  import org.hibernate.cfg.*

  import com.barneyb.Person

  sdf = new java.text.SimpleDateFormat("yyy/MM/dd")
  sdf.lenient = true

  def sf = new AnnotationConfiguration()
      .configure().buildSessionFactory()
  def sess = sf.openSession()
  def tx  = sess.beginTransaction()
  sess.createQuery("delete Person").executeUpdate()
  sess.save(new Person(
    name: attributes.name ?: "Barney",
    dob: sdf.parse(attributes.dob ?: "1980/06/10")
  ))
  tx.commit()
  sess.close()
  sf.close()
</g:script>

No need to compile anything, no need to drop JARs all over your server, nothing.  Write, refresh, persist.  That includes adding new entities, new properties to existing entities, etc.

It's not ready for public consumption at the moment, but that's my top "free time" priority.  For the incredibly impatient, there's a branch in my SVN repository with the current source.  Don't expect anything pretty.  ;)

Railo 3 Beta 2

Railo dropped a second beta last night. Get it here. They've also added a WAR download, though it only works when installed into an existing "express" installation. Hopefully that'll get addressed for the next release.

A couple shining points about the runtime:

  • Array and Struct literals (the [...] and {…} notation) are expressions, exactly as they should be, unlike other CFML runtimes (cough…Coldfusion…cough).
  • Arrays and Structs now implement java.util.List and java.util.Map respectively, greatly easing Java integration. This also allows the Comparators CF Groovy example I published to work correctly on Railo.

Railo fixes Arrays and Structs

I just got a JIRA notice that Michael fixed Railo so that arrays and structs implement java.util.List and java.util.Map respectively. This is great news, because it means it's now possible to pass nested arrays and structs to Java APIs without having to manually rewrap them. From the ticket, it looks like the fix will be available in the next 3.0 beta, though I don't know when that's due out.

On the compatibility front, this means that the three major Java-based CFML runtimes (ColdFusion, Railo, and Open BlueDragon) all have compatible arrays and structs, which is a good thing if you need to write portable code that leverages underlying Java APIs.

CFUNITED Day One

As is typically the case, CFUNITED has a pair of themes.  There's the conference theme, which, as always, is helping CF coders become more empowered by learning about new things (OO, using CFCs, learning frameworks, etc.), and then there's the "backtheme".  This year it's all don't use only CF.  Adobe's integrating Hibernate into CF9, Railo is preaching the benefits of the JBoss platform (clustering, caching, Hibernate, etc.), Groovy has a lot of lovers, and Grails (which is Spring and Hibernate for Groovy) does to.

The integration of Hibernate all over the place is very exciting.  CF-based ORM tools suck, frankly.  Which isn't to belittle Mark or Doug in any way, they've done a fantastic job, it's problems with CF itself that are the issue.  With Railo's "CFC is a class" implementation, Hibernate is directly applicable.  With CF's crazy "a CFC is a bunch of classes in a Map" implementation, I'm not sure how Adobe's going to get it to work.  I'm very much hoping they fix the core issue (which would almost certainly give some nice performance benefits as well) instead of bastardizing Hibernate to get it to work, but we'll see.

Scriptlets in CF Anyone?

My last post about Comparators via CF Groovy was simplistic in nature, but the underlying concept is incredibly powerful.  Here's a similar snippet (from the demo app), this time using a Comparator class:

<g:script>
Collections.sort(variables.a, new ReverseDateKeyComparator())
</g:script>

So what do we have here?  Why it's a snippet of Java embedded directly in your CFML page, and it gets dynamically compiled and executed just like the CFML.  Let me say that again: it's a snippet of Java embedded directly in your CFML page.  It's even better than that, though, because it's Groovy, which is Java plus a whole lot more.

In addition to the scriptlet functionality, CF Groovy provides a classloading framework for Groovy scripts and classes, in addition to the ones provided by the CFML runtime and the JVM.  You can define an extra Groovy classpath for your scriptlets like this:

<g:setPath path="#expandPath('/groovy')#,#expandPath('/packages')#" />

There's no way to tell how the ReverseDateKeyComparator class in the first example is implemented, but it happens to be a Groovy class that I've added to the classpath with the <g:setPath> tag.  That class, just like the scriptlet, is dynamically compiled and executed just like the CFML.  This is also very powerful, because it eliminates the compile/build/deploy cycle that is usually required for Java code in a JEE environment.

Combining these two, you can use <g:script> to execute arbitrary scripts from the Groovy classpath, instead of inlining them:

<g:script name="myScript.groovy" />

This lets you reuse scripts across CFML pages, as well as reusing classes between scripts.

I've added CF Groovy to my Projects page, so that's the place for the latest info, as well as some documentation and the all-important Subversion information.

Comparators in CF with Groovy

I don't know about anyone else, but wanting to create little ad hoc Java classes in my CF apps in a common occurrence for me.  With my CF Groovy project, it's both possible and very easy.  No Java, no compiling, no classloading hacks.

Here's a simple example.  I'm going to create an array of structs and then sort the array based on a specific field value (the 'date' field) of the structs.  Doing this in CF usually means making a lookup struct, sorting that, and then rebuilding the array (but only if you have unique values), or converting to a query and using QofQ to do it.  Both have serious drawbacks, as well as being very circuitous/obscuring.

First the array construction (six items, each with 'letter' and 'date' fields, holding what you'd expect).  Nothing very interesting here.

<cfscript>
a = [];
month = createDate(year(now()), month(now()), 1);
for (i = 1; i LTE 6; i = i + 1) {
    s = {
        letter = chr(65 + randRange(0, 25)),
        date = dateAdd("d", randRange(0, 30), month)
    };
    arrayAppend(a, s);
}
</cfscript>

Now, using the <g:script> tag from CF Groovy, we'll sort it by date using a java.util.Comparator:

<g:script>
Collections.sort(variables.a, {o1, o2 ->
    o1.date.compareTo(o2.date)
} as Comparator)
</g:script>

If you want to compare based on the letter, just change the two ".date" references to ".letter".  You can, of course, make the comparator as complicated as you'd like, including referencing other Groovy classes through CF Groovy's classloading, or other Java classes on your classpath.

You can see it in action at the demo page, or get the full source from Subversion at https://ssl.barneyb.com/svn/barneyb/cfgroovy/trunk/demo/.