Flex (BlazeDS), JMS, and JBoss in a Nutshell

This morning, I published another tech doc for folks' use here at Broadchoice that was appropriate for sharing with the world. It describes how to configure a topic-style JMS destination within JBoss, connect a BlazeDS destination to it, and have a Flex consumer listen for messages from the BlazeDS destinatin (and therefore the JMS topic).

It's a Google doc, is available here:

Flex (BlazeDS), JMS, and JBoss in a Nutshell

Swiz and MockAsyncToken

I've been taking a look at the applicability of Chris Scott's Swiz Framework for use here at Broadchoice. So far, it's exactly what I'd expect - a fairly noninvasive way of wiring dependencies inside a Flex / AIR application that allows use of inversion-of-control.

One thing that threw me, though, was that Swiz approaches business delegates (wrappers for business services like RemoteObjects) from a total RPC standpoint. Instead of passing an IResponder to a new delegate instance each time you wish to use it like most Flex frameworks encourage, you simply write a delegate, instantiate it once in your BeanLoader, and use it as a singleton. Each of its methods that make server-side calls just return AsyncToken instances.

I really like this, as it makes the difference between a simple RemoteObject and a delegate wrapper completely irrelevant - your controller doesn't have a clue if it's talking to a delegate or not.

It did, however, throw me off from something I typically do. I normally write a "mock" delegate for any business service that "pretends" the server is there. Its useful in both unit tests and day to day coding: server may be down, backend code not written, etc.

In order to get this to work with Swiz, however, I had to simulate the presense of an AsyncToken and its related RPC events. Hence, I've cobbled together a MockAsyncToken and MockResultEvent that let you quickly set what you'd like a mock delegate to return:



// Mock'd RPC function
public function getUser() : AsyncToken
{
// just pass the desired server response to the MockAsyncToken's constructor
return new MockAsyncToken(new User());
}

...bam. Instant mock delegate. Thanks to Swiz, the rest of the app doesn't care that it's even there, and if I can use a plain RemoteObject, I never even have to write the "real" delegate.

Code for MockAsyncToken and MockResultEvent (dependency) is attached. Use at your own peril.

Better Living Through Transfer and ColdSpring

We have a live system with customer data and a new requirement comes along that a particular piece of customer data must be encrypted in the database from now on. We already encrypt some columns (using Triple DES - which you might have guessed given the recent posts on my blog and here about mimicking ColdFusion's encryption in Java/Groovy). What is the smallest possible code change to ensure that as any user updates their data in future, this item will automatically be encrypted - whilst still handling the case of legacy data being unencrypted?

We use Transfer for all our persistent business objects and almost all of our business objects have a decorator defined (for validation or some additional business logic). We also use Brian's TDOBeanInjectorObserver to automatically inject services into our business objects - just add a setter for a service and the bean injector takes care of the rest.

Here's the bean injector definition in our ColdSpring file:


<bean id="transferObjectInjector" class="coldspring.transfer.TDOBeanInjectorObserver">
    <constructor-arg name="transfer"><ref bean="transfer" /></constructor-arg>
    <constructor-arg name="suffixList"><value>service,datasource</value></constructor-arg>
    <constructor-arg name="debugMode"><value>true</value></constructor-arg>
</bean>
Normally you would declare it non-lazy but we already do other non-lazy initialization so in our ColdSpring factory initialization code, we do this:

<cfset bf.getBean("transferObjectInjector") />
to force the bean injector to be initialized which, in turn, registers itself as a Transfer event listener (so that it can intercept object creation). The suffixList specifies that any set*Service() method or set*Datasource() method on the business objects managed by Transfer should be matched to beans defined in ColdSpring and injected.

So how do we add the on-demand encryption to our business object's data?

[More]

Writing your Second Model-Glue Application

So the title is a bit of a trick. This really isn't about writing your second Model-Glue application, but more about the kinds of things you see when comparing earlier Model-Glue applications to those you write after having a few under your belt. Most likely a lot of what I'm going to talk about applies to other frameworks as well, so this isn't just a Model-Glue concern. When I arrived at Broadchoice, the older version of our product had already been updated to use the Model-Glue framework. The primary developer team behind this update had just learned Model-Glue. A lot of what I saw looked very similar to how I had built Model-Glue sites when I began. Here are a few items to consider when building your next Model-Glue application.

Model-View-Controller need not be singular...
For those of us who were new to MVC, the idea of nicely separating back end logic from front end views was a godsend. Sure it meant a bit more work up front, but the benefits later on were more than worth the effort. I think this is the thing I appreciated the most about MVC. So, like most people, I began to work with a controller, a ModelGlue.xml file, and maybe a few model files and my directory of views. This worked fine for a smaller site, but as the site began to grow, my XML configuration and controller file began to explode. When I needed to find an event, I was scrolling through 1000 lines of XML. Even if I used a nice naming scheme (more on that below), it was a chore to work with. When I began using Model-Glue, there wasn't a simple solution for this. Luckily the framework added support for XML includes.

I ran into the same issue with my controller as well. The file had become too large to manage. It didn't even occur to me to use multiple controllers until I had done a few Model-Glue sites, but now that I have I wouldn't do it any other way. My typical approach is to break up the controllers by "areas of concern" - which is my way of referring to the major parts of the application. So for example, a typical site may have a User, Product, and News controller. Each would be responsible for handling events related to their areas. So the User controller would handle listening to getUser. Product would listen to getProduct. Etc.

I still keep a controller named, well, Controller, because I find that there are typically events that don't fall into any one particular category. I also still put a few events in the main ModelGlue.xml file.

What's nice about MVC, and where I think it really "sinks in" for developers new to the concept, is that you can update a Model-Glue site to fix this problem and not lose a drop of functionality. So at Broadchoice, I've been slowing breaking things up a bit when there are available cycles. This has zero impact on the product for the end user but has the side effect of making it easier to update the application.

I also recommend breaking up the views folder. It may start small, but before you know it any semi-complex site can grow quite complex. The main idea here is to make it as simple as possible for someone to find the right code when performing updates.

Inconsistent Naming
Ok, so this may be more of an issue for those of us who are anal retentive about naming, but I really get bothered when my event names don't follow a standard naming pattern. Inconsistent naming is an even bigger problem if the files aren't properly broken up (see above). There are no hard and fast rules for what makes a good event name. My typical rule is "area of concern"."action", so I will typically have events like:

  • product.edit
  • user.authenticate
  • planet.destroy

This way it's always clear what type of data (or area of the application) is being worked with, and what type of action is being performed. Once again, the beauty of MVC is that you can make these types of corrections when you have time for it. There are two potential problems with this.

First - you may have existing URLs that rely on certain event names. In the past I've handled this by either using a URL rewrite or by catching the "missing event" error in Model-Glue. Model-Glue 3 adds support for handling missing events directly so this will get even cleaner. While you should put some thought into how you name your events, it may make sense to pay extra attention to those events the users will actually see (and possibly bookmark).

The second problem is a bit harder to fix. If you change the event that is run when a user logs in, it isn't just enough to update the XML. You also have to remember to update the view layer as well. I was never really a big fan of the XFA technique. This is a Fusebox concept whereby you tell the view what to use for particular events. (I believe this originated with Fusebox - if anyone knows better, speak up!) So instead of me hard coding action="index.cfm?event=user.authenticate" in the form tag, I'd pass it to the view layer and make the action dynamic. After doing some refactoring on our product, which made heavy use of XFAs in Model-Glue, I'm really happy they were used. Here is a simple example from one of our views:


<views>
    <view name="body" template="documents/documents.cfm" append="true">
        <value name="xe.view" value="document.document.view" />
        <value name="xe.list" value="Documents" />
        <value name="xe.edit" value="document.document.edit" />
    </view>
</views>

Note the use of the value subkey inside the view node. This will add the values to the viewState. You would then use these when creating any links within the view.

Anything else?
This is - in general - the big things I've noticed when looking at first generation Model-Glue sites. I'm curious to see what others have discovered as well, so please chime in with your comments.

I'll add one more thing to the list - I wish like heck I had made more use of auto-wiring and ColdSpring in general. Until you see a good example of an application that uses this you don't truly get how much work it can save you.

Doing ColdFusion 3DES Encryption in Java (well, Groovy.)

Last night on his blog, Sean Corfield asked if anyone knew how to write raw Java / Groovy that'd give equivalent output from ColdFusion's encrypt() and decrypt() functions when using 3DES / TripleDES / DESede (many names, same thing?) encryption and hex encoding.

I wanted to see if I could knock this out before the West-coast Broadchoicers were awake so that they'd have a day that wasn't blocked by encryption woes.

It turns out that when you use ColdFusion encryption with "hex" as your encoding option, ColdFusion performs two different conversions:

First, GenerateSecretKey() returns the secret key from the underlying javax crypto library as a Base64 string, even when you state "hex". Sensible, really, as there's no reason to support different encodings at this point.

Next, when you encrypt a string, it not only encrypts it but converts it to the desired encoding - in Sean's case, hex.

The attached zip includes a Groovy script solves the problem, performing all of the necessary conversion and encryption. It also includes a ColdFusion script. Running both shows them taking the same input and producing the same output. (For the curious types: both use a key that I generated locally, not a "real" key string!)

It relies on the Xerces library. I'm using the xerces-2.6.2.jar that comes in Hibernate's /lib, but it's available on its own at xerces.apache.org.

How Do You Start a New Job?

Today is my first official day at Broadchoice, though I've been on the development list server and conference calls for a while. I thought I'd blog quickly about how I'm getting settled and see if others have their own ideas or processes that they go through for starting a new job.

  • Read up: Broadchoice has a pretty nice Intranet that contains a lot of information. So all the fun stuff like personnel forms, health insurance, tax forms (whee) and all the rest. Ahh, first day paperwork! I think the only other time I've signed so many forms is closing on a house. :-)
  • Local development: New work means a new Eclipse workspace and new Apache virtual hosts. As a new Apache convert from IIS, the one thing that I miss is the nice management console that IIS provides. The first thing I did when moving to Apache was to write a script that would automatically create new virtual hosts for me. So by filling out a short form, I add a new virtual host to my Apache config, update my hosts file, and optionally create a new Eclipse workspace by copying a default workspace.
  • Source code: If good developers are at least part artist, then source code is our clay. Like any modern development shop, Broadchoice uses source code control extensively. In our case, it's Subversion. That means hooking up to the SVN server and pulling down working copies of the relevant code.
  • Tasks: Broadchoice uses Trac to manage tasks and tickets. However, like many people I think the Trac web interface leaves a lot to be desired. Luckily, we have the Mylyn plugin for Eclipse. This great add-on lets me connect to the Trac repository from within Eclipse and manage tickets. It's great to be able to do this without leaving the IDE. It gives you little message alerts when new tickets come in, and lets you create custom queries for Tasks. So, for example, all tickets assigned to me. Or all tickets associated with a specific release number. It also offers "context" which lets you activate a ticket and then it keeps track of what files you've used while working on that ticket. Any time you go back to that task, the IDE hides everything unrelated and just shows the files that relate to that task. This is really great when you have to jump between tasks since you don't have to think about what you need to open.
  • Organization: I'm fairly anal about how I organize stuff on my computer. That means folders, usually lots of them! I've found that being a bit meticulous about setting things up makes life a lot easier later. In the past I might just create a "broadchoice" folder for documents, and dump everything in there. Later, when there are 100 files in there, I end up regretting my lack of organization. So I try to segment things off at least somewhat: corporate, employment, expenses, projects, etc. It's no extra work to drag a file into the right folder, but it makes things much easier to deal with in the future.
  • Communication: With a number of remote developers, communication is key. The development team makes a big effort to be reachable in a variety of ways. Email is an obvious one. Instant messaging is another. We also use Adobe Connect on occasion, Skype for quick conversations, and of course the good old Phone when necessary. Everyone has an iPhone, which was pretty smart on the part of management. Being geeks, everyone almost always has their iPhone with them, which means email, phone calls, and SMS are almost guaranteed to be seen and answered quickly.
  • Mindset: Starting a new job can be somewhat daunting. You're jumping into something totally new, working on things that may be completely foreign, and maintaining code that others wrote. For many, this may be scary. But I love it. The chance to break new ground and do new things is extremely exciting to me. Working with a team like this means there isn't room for shortcuts or half-measures. When you know the code you write will be scrutinized by people like Sean, you set the bar for yourself pretty high!

I think I've hit on most of the major things I've done in preparation for starting here at Broadchoice. Anyone have other tips or advice?

AIR and Groovy via Spring

As a fun way to while away a Saturday evening, I decided to look at Joe's Behavioral Analytics backend code to see if I could create a Flex-based AIR application that talked to services written in Groovy. There's not really much documentation out there to help so it was a very hit and miss experience but eventually I had a simple AIR application making a RemoteObject call to a Groovy class and getting data back. I'm going to have to talk to Joe about cleaning up the installation I've ended up with but here are the highlights (and I'll blog more about this once I have all the pieces cleaned up):

  • JBoss 4.2.3 GA installed as a Server in Eclipse (using the Web Tool Platform JEE stuff)
  • Spring framework 2.5.5
  • A Spring-based Flex factory that allows Flex Remoting to talk to objects via Spring (author Jeff Vroom)
  • Groovy - set up per Joe's recent instructions
  • BlazeDS providing the Flex Remoting service
Create a Dynamic Web Project in Eclipse and then unzip BlazeDS into it (per the BlazeDS installation docs). Add Spring and the flex.samples.factories.SpringFactory Java class. Configure Flex Remoting according to Lin's instructions to add the Spring factory:

    <factories>
        <factory id="spring" class="flex.samples.factories.SpringFactory"/>
    </factories>
and the context loader:

    <!-- Spring -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <!-- load Spring's WebApplicationContext -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
and the destination for the RemoteObject:

<destination id="place">
        <properties>
            <factory>spring</factory>
            <source>placeholder</source>
        </properties>
</destination>

Create a Flex AIR project and define a RemoteObject that refers to the destination you just defined:


    <mx:RemoteObject id="bcp"
            destination="place"
            endpoint="http://127.0.0.1:8080/bcpbackend/messagebroker/amf"
            >

        <mx:method name="test" result="testResult(event)" fault="testFault(event)"/>
    </mx:RemoteObject>

Add the placeholder bean definition to your applicationContext.xml file:


    <bean id="placeholder" class="com.broadchoice.bcp.Placeholder"/>
com.broadchoice.bcp.Placeholder is a Groovy class that contains a test method (for testing it just takes a string and returns that string plus some additional text).

Living in a Cluster

The Broadchoice Collaboration Platform (BCP) is deployed on a cluster of servers and this has a number of interesting implications for the design of the application as well as the actual deployment process and file system structure used.

I'll be posting several entries on clustering considerations but I wanted to start with something that surfaced with the recent launch of this blog. BlogCFC is part of our standard SVN repository (I'll also be blogging about our source code control processes) and so it is also deployed to the same cluster as the BCP. Each server runs the same code from its own local file system. BlogCFC allows authors to upload images and files that are used as part of the blog entries. If you simply deploy BlogCFC onto each server in the cluster and then create a blog entry and upload an image, that image will be stored directly on the file system of the server on which your request is processed (in fact, the server on which your entire session is processed, since we use "sticky session"). The other servers in the cluster won't know about the image. For user requests that come in to that first server, the image will be served correctly. For user requests that come in to the other servers, the image will be missing.

The BCP has the same issue - it allows authors to upload CSS, images and documents - but we have to ensure that all these uploaded assets are available to all servers automatically and immediately. Our approach was to design the application in such a way that shared assets are stored in specific directory trees that contain nothing but shared assets. We have a NAS - Network Attached Storage - which is mounted to every server as /var/www/html. That contains a documents directory and a custom assets directory - into which all uploaded content is placed. Symbolic links are used to "map" those shared directories to the appropriate place in the deployment directory tree:

/var/www/production/lib -> /var/www/html/lib
/var/www/production/wwwportal/custom -> /var/www/html/custom
We deploy our source tree to /var/www/production (direct from SVN) with lib and custom ignored by SVN. Each server then shares the same uploaded content without needing to use different file paths to how we would deploy to a non-clustered server.

Tonight, I applied the same fix to BlogCFC, adding blog_images and blog_enclosures directories on the NAS and adding symbolic links back into the BlogCFC deployment tree (as wwwblog/images and wwwblog/enclosures respectively). We have not yet dealt with making blog.init.cfm cluster-safe or the XML file generated by the pod manager. For both of those, we actually keep the files under SVN and handle changes as part of a managed process (i.e., by tickets in Trac).

This is just one of many things that need to be considered when designing applications for clustered environments. I'll be blogging about other clustering issues over the next few weeks.

Numbers are a useless emotion: A year of traffic in one single impression

They say a picture is worth more than thousand words and yet in almost any web analytics package all we get are numbers. Ok, they have pie charts, bar charts and the obligatory map overlay, but if you have over a 100 reports you need to be able to fill up the screen, right? For the past year I've been using a lot of different web analytics packages and I've become more and more convinced that numbers tell you very little, especially if they can not be compared with other numbers.

I'm all about shiny stuff and pretty pictures so last night I tried to compile a full year of traffic in one single picture and this is the result:

[More]

Creating an Eclipse-based Groovy Development Environment for TDD

Within the system I'm building at Broadchoice, we're exploring the use of Groovy, Spring, and Hibernate in combination. The first step in building a system using this stack is creating an Eclipse-based environment in which we can write and test our code. To help people do this, I've published a Google document entitled Creating an Eclipse-based Groovy Development Environment for TDD.

As it doesn't contain any "technical secrets" (we don't really have the concept of a technical secret at Broadchoice!), I thought it'd be handy to share it with the world.

I've still got more to document, including how to integrate TestNG tests with Spring and how build (and effectively test!) a Hibernate-enabled Groovy+Spring project. A lot of this is the result of reading multiple books and a good deal of Googling / piecing together information, so I hope you enjoy it in distilled, ready-to-consume formats!

More Entries

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