Groovy JavaScript

Many moons ago I blogged on how you can use Groovy to generate HTML files. I'm not doing this a lot at Broadchoice, only for a few administration type pages, but I had to work within this framework again this morning and ran into a little issue with JavaScript. I wanted to add a bit of jQuery to my page. Should be simple enough, right? My HTML document had an existing head that looked like this:


head {
    title 'TPS Reports'
}

This generates:


<head>
<title>TPS Reports</title>
</head>

So adding jQuery in should be as simple as this:


head {
    title 'TSP Reports'
    script(type:'text/javascript',src:'js/jquery.js')
}

Right? Unfortunately, it isn't quite that easy. Sure, this works and generates out what you expect:


<script type='text/javascript' src='js/jquery.js' />

But notice the self-closing script tag? This doesn't work in some browsers. I thought perhaps it was just IE, but it didn't work in Firefox. Safari had no problem with it. (And I'd love to hear a good reason on why a self-closing script tag doesn't work. Seems like a bug to me!)

Unfortunately, I couldn't figure a way to tell Groovy's HTML Builder to include a 'real' closing tag as opposed to a self-closing tag. I then figured out this simple hack:


script(type:"text/javascript",src:'js/jquery.js',' ')

Notice the last unnamed argument? This will be used as the content for the script tag. You end up with:


<script type='text/javascript' src='js/jquery.js'> </script>

Which works just fine in Firefox and Safari. Silly, but effective. One more quick tip, although it's kind of obvious. I wasn't quite sure how I was going to write my JavaScript code since everything has to be formatted just right inside the builder. Then I remembered that I could simply provide the code as an argument:


def code = """
console.log('yep, Im running');
"""

html.html{
    head {
        title 'Space/Feed Actity Report'
        script(type:"text/javascript",src:'js/jquery.js',' ')
        script(type:"text/javascript",code)

ColdFusion to Groovy - List issue

I recently ran into an interesting issue involving ColdFusion, Groovy, and Lists. I thought I'd share, but before I go any further, please remember that I am still very new to Groovy. There is a good chance that I may mis-label something. So with that said, what was the problem?

The mobile version of our application is a ColdFusion web site that speaks to Groovy via ColdSpring configured beans provided to our Model-Glue application. This makes it incredibly easy for me to reuse all the Groovy services we built for the AIR application. When I need to get some content, for example, I can do:


<cfset arguments.event.setValue("task", beans.contentService.getCurrentUserContentItem(javaCast("long",id)))>

The only clue that something non-CFML is going on here is with the javaCast. Outside of that I may as well be using a 100% pure CFML application.

In general, this just plain works. Period. However, last week I ran into an odd issue with one method that took a list as an argument. I knew that a list in Groovy was an ArrayList, and that should correspond to an array in ColdFusion. I created my object, let's call it ob, and then ran code similar to this:


<cfset beans.contentService.savePublications([ob])>

Note the use of [] to shortcut the need for me actually creating an array. If that is confusing, think of it as:


<cfset var arr = arrayNew(1)>
<cfset arr[1] = ob>
<cfset beans.contentService.savePublications(arr)>

That should work, right? Unfortunately it didn't. I kept getting errors saying that my data was some odd, generic Java object as opposed to the casted object it should have been within Groovy. I tried a few things - like for example, changing my closure from:


contentItems.each { contentToSave ->

more logic here....
}

To


contentItems.each { Content contentToSave ->

more logic here...
}

I thought maybe the extra hinting there would help. All that did was move the error up to the beginning of the closure. Eventually I gave up. I wrote a new method in Groovy that took a singular object and simply called the list version. While this worked, I wasn't terribly happy with it, and shared the problem with my coworker. Sean suggested that the problem may lie in the array ColdFusion was creating. He suggested using an ArrayList in CF and then passing that to Groovy. I modified my CFML like so:


<cfset var al = createObject("java", "java.util.ArrayList")>
<cfset pub = createObject("java", "com.broadchoice.bcp.model.beans.Publication")>
<cfset pub.content = bookmark>
<cfset pub.space = space>
<cfset al.add(pub)>
<cfset beans.contentService.savePublications(al)>

This worked like a charm. It was a bit more code to work with, but at least I could use the same service methods AIR was using for the same business logic.

Plain Text and HTML Emails via Spring

Last week I had to add email support to our application. While this is trivial in ColdFusion, I was expecting quite a battle with Java. I had hoped that maybe Groovy would have a simple solution perhaps, but turns out it was even easier than I could imagine.

My experience with Spring has been pretty minimal. I know how to work with it, and I know how to add stuff and set dependencies and stuff, and so from that it meshed well with what I knew of ColdSpring. But Joe informed me that Spring was a lot more than just a Inversion of Control framework. It also ships with a set of additional features to help developers. So for example, scheduling stuff (which CFML developers get via the scheduler in the Admin) is easy with Spring. As you can probably guess, mail is easy as well.

I won't go into the full details here, but I'll point to the documentation on it and you can read it yourself.

Ok, so far so good. The problem I ran into though was moving from plain text messages to a mail message that supported both the plain text and html text at once. Here was the original code I had for the plain text message:


def subject = "Subject here..."
def emailStr =
"""
$user.firstName $user.lastName,

Etc etc
"""
def msg = new SimpleMailMessage(templateMessage)
msg.setTo(email)
msg.setText(emailStr)
msg.setSubject(subject)
    
try{
mailSender.send(msg)
}
catch(MailException ex) {
println(ex.getMessage())
}

The above should be easy enough to read. The templateMessage object is code injected by Spring and contains the connection information for the mail server (server, port, username, password). That stuff is configured in Spring which is sensible. I also configure the from there since all mail will be using one main from address. After that, all I have to do is set the subject, the To, and the text, then fire it off.

I had hoped that the setText method would perhaps have options for sending HTML email as well. Unfortunately that wasn't the case. (Hey, they did call it simple, didn't they?)

In all my searches at Google I was unable to find a simple example of this. I saw examples using attachments and HTML email, but not a plain+html example. The API docs for things I thought would be a good alternative were pretty confusing. My main issue was that everything wanted a MimeMessage object, and I couldn't figure out how to create it. Finally I realized that Spring had sent me a mailSender object (it's what I was using to send the mail) and had an option to create a mime message:


def msg = mailSender.createMimeMessage()

I could then use a MimeMessageHelper object like so:


def msg = mailSender.createMimeMessage()
def helper = new MimeMessageHelper(msg,true)
helper.setTo(email)
helper.setSubject(subject)
helper.setText(emailStr,htmlStr)
mailSender.send(msg)

That worked like a charm. I probably got half the terminology wrong above, but hopefully this will help others as well. A big thank you goes to Andrew Powell for his help on this.

Meaningful method names are great!

I came across (and added a bit to) a great snippet of code today in the Workspace codebase while fixing a bug on QA. The code represents just how you can use OO to encapsulate complex logic into meaningful behaviors of entities.

We have a business rule that says the following:

"The current user may save a membership in a workspace may be saved if all of the following are true:

1. The membership's user is not already a member in the space. 2. The current user is the owner of the space OR the space is marked public and the current is a member of the space's group."

Thanks to some good method names, the code is easier to understand than the English!

Here it is, in code:


if ( !membership.space.containsMember( membership.user )
     && (
        membership.space.isOwnedBy( currentUser )
        || ( membership.space.isPublic && currentUser.isAMemberOf( membership.space.account ) )
     )
)

Thanks to whichever of my coworkers originally wrote this - it was easy to modify to suit a new need!

Caveat Container

I said that I'd blog about a couple of painful lessons learned and that's a bit overdue. Sorry, I went to Holland for a week! However, here's one of those lessons learned...

If you work with containers in Java (collection classes), you'll find that they have a contains(obj) method. The idea is that you can quickly check whether a given object is already in the collection by saying:


if (myCollection.contains(myObject)) ...
In many cases, you'll find this "just works" because contains() has the same idea of "equal" that you do for your objects. That is, it checks whether that exact same object is a member of the collection. Unfortunately, there are situations where "the same" object might be a separate instance that just happens to have all the same data (or at least the same key data). That can happen pretty easily when you are working with an ORM (like Transfer - although in our case it's Hibernate). You may be manipulating an object with, say, id = 783 and ask the ORM to load it from the database (or cache) so you can work on the "original" object. If the object you were working with has become disconnected from the ORM's cached version, you will now have two instances of the "same" object. They are "equal" as far as you are concerned but contains() will not consider them the same and you might be surprised to see it return false when you know the object is in the collection!

This happened to me. My unit tests all passed but they had no disconnected objects. The real application began to fail and it took me a while to realize why.

For me, objects are "equal" if their id properties are equal (and they are the same type of course). In my Groovy domain objects, I define equals() to specify this behavior and Groovy conveniently calls equals() when I say objA == objB. Operator overloading is very useful (and easy) in Groovy and it can help make your code much more readable.

Unfortunately (for me), Java's collection classes don't respect that when contains() is called.

Fortunately, Groovy provides a fairly simple workaround. You can use the find() method and a closure to specify the filter. find() returns the first matching object - or null if no objects match. myCollection.contains(myObject) can therefore be replaced with myCollection.find { it == myObject } or, if you want to be explicit, myCollection.find { obj -> obj == myObject }

Since CFML does not allow you to compare objects directly, you're always going to have to write your own equality method. That means that any collection-based operations you do must explicitly call the appropriate equality method so, hopefully, you won't fall foul of Java's very literal "equality" test for the contains() method. If you work across both Java and CFML tho', you'll need to bear this in mind.

Is it ColdFusion or Groovy?

Here at Broadchoice we've been working on our new product for close to three months now. I've gotten a crash course in Groovy, Spring, and Hibernate, all of which are slightly familiar to me from my time with ColdSpring, Transfer, and Java. I'm really digging these new technologies, but of course, I'm a die hard ColdFusion user at heart. A few weeks backs I needed to work on a quick iPhone web application prototype. Joe set up the connection and all I had to do was write CFML (lucky me). Little did I know that along with setting up basic CFML compatibility on the server, Joe also added one of the slickest things I've seen ever in my life as a developer.

The application I'm working on is pretty simple, but I wanted to use Model-Glue 3 for it since - well - you never know when a simple prototype will turn into a large, complex application. The following code snippet comes from a controller used to load bookmarks:


<cffunction name="getBookmarks" output="false">
<cfargument name="event" />
<cfset var u = arguments.event.getValue("currentuser")>

<!--- In theory currentuser should always exist, but... --->
<cfif not isSimpleValue(u)>
<!--- space only? --->
<cfif arguments.event.valueExists("space")>
<cfset arguments.event.setValue("bookmarks", beans.contentService.findContentBySpace(arguments.event.getValue("space"),["Bookmark"]))>
<cfelse>
<cfset arguments.event.setValue("bookmarks", beans.contentService.findUsersContent(u,["Bookmark"]))>
</cfif>
</cfif>

</cffunction>
Nothing in the above code should be too odd or even that exciting really. I'm using a service (injected via the beans scope in Model-Glue 3) to retrieve my content. My controller begins with...


<cfcomponent output="false" hint="I am a Model-Glue controller." extends="ModelGlue.gesture.controller.Controller"
beans="contentService,config"
>

Note the beans value specifies which beans configured in ColdSpring should be passed to my controller. I love this new automation in Model-Glue 3. If you open up my ColdSpring.xml file, you will see my beans configured:


<bean id="config" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
<property name="config">
<map>
<entry key="profileimageroot"><value>/some url you dont need to know</value></entry>
<entry key="filesroot"><value>/something else you dont need to worry about</value></entry>
<entry key="perpage"><value>10</value></entry>
</map>
</property>
</bean>

Hmmm. Ok, there's my config bean, wheres my contentService bean? Oh yeah - here it is:


<bean id="contentService" class="com.broadchoice.bcp.services.ContentService">
<property name="dao" ref="contentDAO"/>
<property name="sessionFacade" ref="sessionFacade" />
<property name="sharedFileGateway" ref="sharedFileGateway" />
<property name="eventMessageDispatcher" ref="eventMessageDispatcherService" />
</bean>

You can find the above in our Spring file. Just in case the above didn't quite make get through, let me make it real nice and obvious:


<cfset arguments.event.setValue("bookmarks", beans.contentService.findContentBySpace(arguments.event.getValue("space"),["Bookmark"]))>

The above line of CFML is using a bean injected from Spring, not ColdSpring, and points to a Groovy file. This is the same Groovy code used to drive the AIR application. No createObject("java") here baby. I'm using the Groovy code just like it had come from a CFC. This is done using a ColdSpring/Spring adapter that Joe wrote. It lets ModelGlue get Java-based beans from Spring. (I'm simplifying it here a bit, but hopefully you get the significance of that!) Once that connection is done, you can easily get beans from the Spring file and inject them into your controller. So for example, when my UserController wanted do handle login, I added: beans="userService,config" and then simply ran a userService.validateAndLoad on the authentication information.

It's always been easy to use Java from CFML, but never has been so sexy! Now to be fair, I did have to use a JavaCast once or twice, but not nearly as much as I would have thought.

Creating Flex "remoting proxies" in Groovy

When you're developing a RIA based on a set of business services, it's rare that your domain model is simple enough to just expose the raw services to Flex. Often, you'll have spots where you need to work in thinner DTOs or do a little extra work specific to Flex.

While you can do a fair amount of this with AOP, that's often like hunting flies with an elephantswatter. Instead, I've been creating remoting services that defer any method not explicitly defined to the business service they wrap. If I need to add a smattering of "advice" before or after a method call, I then just define the method and add my bits.

Here's an example, using a fictitious "LoginService" being proxied by "FlexLoginService."


class FlexLoginService
{
    // Injected by Spring
    LoginService loginService


    /**
     * By default, defer invocations to wrapped LoginService
     */

    def methodMissing(String name, args)
    {
        return loginService.invokeMethod(name, args)
    }

    /**
     * Wrap the "login" method to deal with the UserDTO sent from Flex
     * - the business service expects a full-size User object
     */

    login (UserDTO userDTO)
    {
        def user = new User(username: userDTO.username, password: userDTO.password)
        loginService.login(user)
    }

}

Groovy Multiline Strings + HQL = Bliss.

In the home screen / dashboard for the Broadchoice Workspace, the second folder ("Spaces") in the tree on the left shows which workspaces Jack Conner participates in.

The data access method that generates this list shows one of my favorite things about combining Groovy and Hibernate: using Groovy multiline strings to create and run an HQL query.

In Groovy, triple-quotes indicates a string that spans multiple lines, solving one of my least favorite things about Java / C# / many other languages: writing well-formatted SQL was a pain. ColdFusion handles this wonderfully with the CFQuery tag. Groovy can be almost as pretty.

Here's what the underlying method for that list looks like: very familiar for ColdFusion folks, especially for Transfer users:


List findUsersJoinedSpaces(User user)
{
    return getHibernateTemplate().find (
        """
            select
                membership.space
            from
                SpaceMembership as membership
            where
                membership.user = ?
        """,
        user
    )
}

Groovy HTML

No, that's not "cool" HTML, but HTML ala Groovy. This week I had my first experience writing Groovy for HTML and I thought I'd share my thoughts. I just want to warn folks that a) I'm a rank newbie at Groovy and b) any code I show is probably horrible and inefficient. With that being said, let me just say first off. The experience of HTML is Groovy is... odd. The only thing I can compare it too is writing by using a mirror instead of actually watching your hand. While it is certainly not that hard, not hard at all really, it's just unlike anything I've done before!

Before I show the code, there are two concepts I have to cover. I'll repeat the warning I gave above. I learned about both these things over the past few days. Both features really deserve a lot more explanation then I'm giving it, but for those who know nothing about Groovy I want to give a bit of context behind what I'm doing.

[More]

Behind The Curtain

As you may have guessed from the content of our earlier blog posts, we're working on an AIR application that involves some sort of real-time collaboration. As you may also have guessed from the slower flow of postings since mid-August, we've been very busy working on that application!

Broadchoice Workspace blogWe're finally ready to start showing the world what we're working on and to talk about the concepts and technologies behind it. We're also taking early signups for the forthcoming limited beta program. [You can download the public release from the main Broadchoice website]

This blog post contains the first public unveiling of the application and its capabilities. The fundamental concept of the application is to provide a central way to collaborate with your colleagues (or friends). All users have a personal workspace containing files they have uploaded, a blog, a GTD-style task manager and useful bookmarks they have found.

[More]

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002. Contact Blog Owner