Friday, August 27, 2010

jQuery Validate and Checkboxes

As I start this post, a quick aside.. I've had some discussions with a few devs lately on the use of the id attribute versus the name attribute on HTML input elements.  IMO, id is a unique identifier, whereas name is used to tie fields such as checkboxes together, which today's post deals with.  The result looks like this:


For what it's worth, I never use the name attribute on input elements except when it is of type checkbox, but I digress... ;)

I had the need to require two or more checkboxes to be checked on a form recently.  I am using jQuery Validate for the form validation logic.  This is the first time I've had to roll my own validator since starting with jQuery Validate as it's defaults are pretty inclusive.  Creating a custom validator is simple.  The code looks like this:
$.validator.addMethod(
 'multiplecheckboxchecked',
 function (value, element) {
  var aChecked = $('input[name='+$(element).attr('name')+']:checked');
  return ( aChecked.length > 1 ) ? true : false;
 }
);
Breaking it down,  use the addMethod() function to define a new rule in the form addMethod(name, callback, message).  In my validation logic I change the color of the container div so I do not need the message attribute.  The name attribute specifies the rule name when we assign it to an element when creating the validator.  The callback is the function we will use to validate the form field.  The callback method gets two parameters by default: value and element.  Value is the value of the form field being validated.  In the case of a checkbox this is a bit weird.  We get only one element passed through which has the name value we specify in our rules definition.  The element is the actual form element, and for a checkbox we can use this to our advantage by grabbing the name attribute to get all of the checkboxes bound by the same name.  Line 4 shows our selector: 'input[name='+$(element).attr('name')+']:checked'.  This tells jQuery to get all input controls with a name matching our checkbox group name that are also checked.  This selector returns an array of elements, and we use the length of that array to tell how many boxes have been checked.  In my case I needed at least two, so I return true if two or more are checked, false if one or less are checked.

Using the rule then looks like this:
rules: {
 frictiontypeid: 'required',
 checkboxgroupname: 'multiplecheckboxchecked'
}
I also had to use a custom highlighter which is simple to override for checkboxes:
highlight: function(element, errorClass, validclass) {
 // if the element is a checkbox, highlight the entire group
 if ( element.type == 'checkbox' ) {
     $(element).parents('.ctrlHolder').addClass('error');
 } else {
  $(element).parent().addClass('error');
 }
},

Monday, August 23, 2010

More ORM Weirdness

NOTE: the first part here addresses CF 9.0.0.  9.0.1 does not fix this, but expands the weirdness.  9.0.1 behavior is the second half of this post.

In my last post I learned via @brian428 that the behavior was correct since the collections need to be loaded or else ORM doesn't know if they should be deleted from the collection or not.  EntityMerge() did not work, but loading based on length of the passed ID did (again, thanks Brian).

The new weirdness is when I return the loaded object back via JSON.  There are two child collections: Entities and FocusAreas.  Entities are null and lazy loaded.  FocusAreas contains one record, and is also lazy loaded.  Note the JSON:
{"obj":{"entities":[],"id":"8ab2932d2a8529d6012a856916c40002","focusareas":,"errors":[]}
See that focusareas returns nothing, whereas entities returns an empty array. The error comes on the client since when I eval() in JavaScript it tries to set focusarea to ',"errors":[]}' and then sees no proper closing for the JSON string. Setting lazy="false" on the focusareas relation fixes the issue, but then I have to return the focusareas, which I do not need. What I would expect to see is:
{"obj":{"entities":[],"id":"8ab2932d2a8529d6012a856916c40002","focusareas":[],"errors":[]}
The error would be fixed by setting the value of getFocusAreas() to an empty array upon initialization.

So here is where Brian suggested I install the CF 9.0.1 updater.  At first I was pleased.  When I returned the value after an entitySave(), it did not return entities or focusareas.  w00t!  To be sure, I then loaded the focusareas with getFocusAreas().  They still were not returned!  Setting lazy="false" also had no bearing.  There was nothing I could do to get them to return.  For a sanity check I dumped the parent object right before the return and got this:


I've cleared my cache and restarted CF.  The returned JSON is still:
{"obj":{"id":"8ab2932d2a8529d6012a856916c40002","title":"Test Project"},"errors":[]}

ColdFusion entitySave() Issue

I'm trying to use entitySave() and am finding a weird behavior.  My parent object links to the child object as such:
<cfproperty name="focusareas" singularname="focusarea"
          fieldtype="one-to-many" type="array" cfc="FocusArea"
          fkcolumn="parentid" cascade="delete" />
When I save the parent, I am using an Ajax call and the service proxy uses an entityNew() to create the child, sets its id and other variables and then calls entitySave().
var parent = entityLoadByPK('Parent', arguments.id);
  parent.setID(arguments.id);
  parent.setTitle(arguments.title);
  entitySave(parent);
The logical behavior is that entitySave() determines if the record should be inserted or updated. What happens is pretty strange though. Check out the Hibernate log:
Hibernate:
    update
        Parent
    set
        title=?
    where
        id=?
Hibernate:
    update
        FocusArea
    set
        parentid=null
    where
        parentid=?
The wackiness is that entitySave() does indeed perform an update as opposed to an insert as expected, but then disconnects itself from the child record. If I instead do an entityLoadByPK() and then set all values, everything works as expected. The issue with this is I should not have to check and see if the parent is new and perform an entityNew() or entityLoadByPK() explicitly. This is what ORM does for you. Bug? Thoughts?

Thursday, August 12, 2010

Custom Ajax Callback Arguments for jQuery

I had the need to pass a custom argument to a callback function upon a successful Ajax call today.  Using jQuery for my current project I needed to find the standard way to pass custom arguments.  The API didn't list anything so I turned to Google.  Google 'suggested' using closures.  The solution would look like this:
function myCallback(o, arg) {
  // do stuff with the custom argument
  alert(arg);
}

$.ajax({
  url: 'myproxy.html',
  success: function (o) {
    myCallback(o, 'myvalue');
  }
});

What occurs above is that when the success callback function is called it passes the object returned from the asynchronous call, as well as the custom value which is explicitly defined to the inner function.  It works, but I'm not entirely happy with it.

After reviewing the jQuery API docs I decided to use the context attribute instead.  Seems slightly less kludgy to me.  It looks like this:
function myCallback(o) {
  // do stuff with the custom argument
  alert(this.myVar);
}

$.ajax({
  url: 'myproxy.html',
  success: myCallback,
  context: {myVar: 'my value'}
  }
});

Whatever is passed into 'context' becomes the context of the callback function.  This is meant to be used to pass an actual context, such as the entire document or an element within the document.  This is still pretty hacky.  What I would prefer is the type of behavior YUI has, which allows an additional attribute to be passed with the asynchronous object, which is then passed through to the callback automatically:
function myCallback(o) {
  alert(o.argument.myVar);
}

var callback = {
  success: myCallback,
  argument: {myVar: 'my value')}
}

YUI.util.Connect.asyncRequest('GET', 'myproxy.html', callback);
In perusing the jQuery source, it seems pretty easy to add this functionality.  I'm new to jQuery so I'm not sure how forks and such occur.  Is there an easier method?

Tuesday, August 10, 2010

Cascading deletes in ColdFusion ORM

I started the delete functionality of my application today, for which I am using ColdFusion ORM, and I noticed puzzling behavior when deleting a parent object.  This example will use the following database design:


The relationship between a Story and its Tasks is one to many.  Task.storyid is a foreign key that cannot be NULL, as a Task cannot exist without its associated parent Story.  The ColdFusion classes would look like this:

Story.cfc
<cfcomponent displayname="Story" hint="I am the Story class." persistent="true">
  
  <!--- properties --->
  <cfproperty name="id" fieldtype="id" type="string" generator="uuid" unsavedvalue="-1" length="32" />
  <cfproperty name="name" type="string" />
  <cfproperty name="tasks" singularname="task"
          fieldtype="one-to-many" type="array" cfc="Task"
          fkcolumn="storyid" cascade="delete-orphan" />
  <!--- constructor --->
  <cffunction name="init" returntype="Story" access="public" output="false" hint="Constructor">
    
    <cfscript>
      setID(-1);
    </cfscript>
    
    <cfreturn this />
  </cffunction>
  
</cfcomponent>
Task.cfc
<cfcomponent displayname="Task" hint="I am the Task class." persistent="true">
  
  <!--- properties --->
  <cfproperty name="id" fieldtype="id" type="string" generator="uuid" unsavedvalue="-1" length="32" />
  <cfproperty name="storyid" type="string" />
        <cfproperty name="summary" type="string" />
  <!--- constructor --->
  <cffunction name="init" returntype="Task" access="public" output="false" hint="Constructor">
    
    <cfscript>
      setID(-1);
    </cfscript>
    
    <cfreturn this />
  </cffunction>
  
</cfcomponent>
Story.cfc defines the one-to-many relationship to it's children on line 6 by defining the relationship type, specifying the cfc that defines the child object, and by providing the foreign key column.  The other important bit here is the cascade attribute.  All cascade options may be found here.  (Note: I also tried 'delete' for the cascade attribute, but it had the same effect.)

When we perform an entityDelete() on the parent Story, I expected the child to delete.  Instead, I received the following error:
Error 1048: Column 'storyid' cannot be null. Root cause :java.sql.BatchUpdateException: Column 'projectid' cannot be null
By looking at the hibernate logging I could see that the following was attempting to occur:
  1. Load all objects in the relationship
  2. Set the storyid to NULL
  3. Delete the parent object
  4. Delete the child object
This order of events doesn't make sense, since in a one-to-many relationship as we defined above, storyid could never be NULL as it would break our model (Tasks only exist within the context of a Story).

To get the delete to cascade properly, I had to remove the required attribute of the FK column constraint. Why is this bad?  Well, without the requiring a NOT NULL storyid in the Task table, we allow a developer to persist an orphaned Task (one that never belongs to a Story).  While application code should prevent this from happening, the database should also enforce this policy by defining a proper schema.

The question is do the ends justify the means?  It was easy to get the cascade to function properly by breaking the database design, but now the schema does not properly enforce model constraints (in the real project I actually had 9 FK constraints across 7 tables).  The alternative is to create a delete() method in the Story object which deletes the Task before deleting the Story.  I don't like that since it does not override entityDelete() and goes around ORM as it should be implemented.  Thoughts?

Thursday, August 5, 2010

jQuery Validation Plugin and Uni-Form

I'm using Uni-form on my current project and it is pretty structured in the way elements are nested and classed (and rightly so).  One thing we are taking advantage of is the error notification.  As opposed to giving a small error message, the field div is colored a light shade of red.  Seems like a positive user experience to me as there is no question which fields are in error.
I also usually perform validation via a javascript class I've been using for awhile, but it is clunky and time consuming.  Since I'm embracing jQuery on this project I knew there had to be a good validation plugin.  The one I am using is named simply jQuery plugin: Validation. The docs are decent and the plugin has been around for a few years.  It also validates most of the types a web application would need.  Another cool thing is that it allows field grouping for validation which I could see being handy.

The default behavior is pretty standard in that it will add an error class to the field and append a label with the error message.  Each error message may be overwritten by validation type across the entire validator, or right down to the element level.  9 times out of 10 this would be awesome.  Since I was using Uni-form's error schema, this didn't work for my application.  In Uni-form, a single form element is grouped together with its label and a metadata hint like the following:
<div class="ctrlHolder">
      <label for="">Text input</label>
      <input id="txt" name="txt" value="" size="35" class="textInput" type="text">
      <p class="formHint">This is a form hint.</p>
    </div>
What I needed was to add an error class to the parent div that contains the text input control.  I tried several different methods of achieving this, but the one that worked for me was to use the 'highlight' and 'unhighlight' configuration properties of the validator.  The setup for the validator looks like this:
// load the validator when the DOM is ready
  $(function () {
    $.validator.messages.required = '';
    var validator = $('form').validate({
      // disable checking on every event except submit      
      onkeyup: false,
      onfocusout: false,
      onclick: false,
      debug: true,
      // define the rule for our text field to be required
      rules: {
        txt: 'required'
      },
      // function to call when the form has passed validation and ready to be submitted
      submitHandler: function () {alert('form submit!');},
      errorPlacement: function () {},
      highlight: function(element, errorClass, validclass) {
        $(element).parent().addClass('error');
      },
      unhighlight: function(element, errorClass, validclass) {
        $(element).parent().removeClass('error');
      }
    });
  }) 
Getting the parent div was easy enough using jQuery and the element passed back into the hightlight and unhighlight methods. We just had to add a class when the error is caught, and remove the class when the error has been cleared.

You'll also note that I needed to disable the default behavior which appends a label containing the error message after the form control.  This was achieved by passing an empty function to the errorPlacement configuration property as seen on line 16 above.

One caveat to using the Validate plugin is that you have to have a name attribute on all form fields (at least those you want to validate, all if you don't want to see any errors in debug mode). I generally only include an 'id' attribute, so this hung me up for a bit (thanks @boyzoid)

The complete example can be downloaded here.

Wednesday, August 4, 2010

Kool-Aid - now available in ORM flavor!

A few years ago I had the opportunity to play a part in the great ColdFusion OOP debate.  Apparently it still rages on in the form of OO Architecture, and most recently ColdFusion ORM.  So today, while learning CF ORM, I came upon the issue of a lookup table.  You know the sort, one that contains n values that populate a dropdown control.  To create a simple example, lets use a Developer class with a many-to-one relationship of beer preference.  The ERD would look like this:


So the question is, if I wanted to populate a dropdown control, what do we do?  I knew what made sense in my mind but I want to make an attempt embrace CF ORM, so again today I decided to use a lifeline and reach out.  The answer I received was CF ORM 'logic' (air quotes added by the writer ;) ) would say we create a Beer class and use entityLoad('Beer') to create an array of all possible instances of beer, then loop over that array of objects and call getID() and getName() on each instance to populate the dropdown.  Before you say, "But we can lazy load them", sure we can.  But we need each and every class to get all of the beer varieties.  Knowing the CF community's affinity towards a multitude of fine microbrews this list could get pretty long.  I guess a factory reusing object instances could help here but its a dropdown, and this becomes architecture for the sake of architecture (but see how your mind started to wander there - heh).

My logic dictated that I should create a gateway and write a line of SQL, instantiate the gateway as a singleton and we can even cache the query. This means we create one object, do one database read, and sit there and listen for requests.  To that end I created a SelectorGateway class, created a method to select all beer varieties from the selector table, ordered them by name and returned them to the caller as a query.  The singleton was instantiated with the datasource passed in from this.ormsettings.datasource for maintainability.

What I am attempting to illustrate via this simple example is the continued 'architecture for the sake of architecture' mindset that exists within our community.  Keep in mind to always use the best tool for the job, and if something just doesn't make sense to you, it probably doesn't make sense period!  Also, following an agile development philosophy make smart architectural decisions, but don't plan for 10 steps down the road when 99% of the time those steps will never be necessary, but your client still has to pay for them.

All this being said, there may be a better way to perform the above.  I'd love to hear other suggestions!

Tuesday, August 3, 2010

ColdFusion 9 ORM and the unsavedvalue Attribute

I was working on a project today that I decided to use with CF 9 ORM and ran into an issue while saving a new record. The database I am using is MySQL 5.1. The error I was getting:
Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
Google had some stuff to say, primarily about unrelated solutions, so I decided to use a lifeline and phone a friend. Marc Esher apparently has seen this (amongst some of the other less than helpful Hibernate errors CF causes) and suggested using the 'unsavedvalue' attribute. Worked like a charm so I decided to post here...

The class in question:
<cfcomponent displayname="Project" hint="I am the Project class." persistent="true">

<!--- properties --->
<cfproperty name="id" fieldtype="id" type="string" generator="uuid" length="32" />
<cfproperty name="title" type="string" length="75" />
...

<!--- constructor --->
<cffunction name="init" returntype="Project" access="public" output="false" hint="Constructor">

<cfreturn this />
</cffunction>
</cfcomponent>
I'm using a uuid PK and the MySQL database table does not autogenerate the PK so CF ORM needs to handle this, hence the 'generator' attribute on the id tag. What seems to be occurring is CF tries to commit the instance when I call entitySave(), but sees it as a update as opposed to a create. Marc's suggestion to use the 'unsavedvalue' attribute lets CF know that it has not saved the record yet, forcing it to create a new record. The updated CFC:

<cfcomponent displayname="Project" hint="I am the Project class." persistent="true">

<!--- properties --->
<cfproperty name="id" fieldtype="id" type="string" generator="uuid" unsavedvalue="-1" length="32" />
<cfproperty name="title" type="string" length="75" />
...

<!--- constructor --->
<cffunction name="init" returntype="Project" access="public" output="false" hint="Constructor">

<cfscript>
setID(-1);
</cfscript>

<cfreturn this />
</cffunction>
</cfcomponent>
The 'unsavedvalue' attribute is being set to -1 (which is safe even if you are using a numeric PK). When CF ORM creates an instance of the Project class it automatically calls the init() method for us, which in turn sets the starting ID value to -1. When entitySave() is called, CF ORM checks the value of the id field before committing the object and correctly creates a new method.

Monday, August 2, 2010

My first Swiz Application

So I'll be doing more Flex development in my new position (and will also be touching CF a bunch more as an aside), and I decided to take another look at Swiz. I'm not a big frameworks guy, but in Flex there is a definite need to mediate events which I know Swiz does well, so I decided to take a peek.

I decided to hit a few things at once with my first Swiz application, a sort of technical spike for the project work I will be doing. For this example I needed to map relationships between entities. I found Mark Shepherd's SpringGraph component which sounded like what I needed. It
"displays a graph of objects that are linked to each other, using a force-directed layout algorithm".
Perfect.

Next, I needed a persistence layer. I've gotten to play around with CouchDB a bit for prototyping, so I decided it would be great for this proof of concept. Why?
  1. Dynamic model
  2. Static queries (views)
  3. Restful interface
The latter is the most important to me here since, while the first two are important in the long run, a restful interface means I do not need a service layer to proxy my db requests. I've enjoyed prototyping in CouchDB previously and this got me up and running quickly. If you don't already have CouchDB installed and are on Windows, there is a windows binary installer that works nicely. I named my database 'swizsample'. After you create the database you can copy this file into your data directory to load the data for this example (Linux: /usr/local/var/lib/couchdb/ or Windows: %couch%\var\lib\couchdb\).

After installing Flash Builder 4 (with the Flex 4.1 SDK) as a plugin to eclipse, I grabbed my necessary libraries (included in the attached sample project):

3. as3corelib 0.93 (for deserializing JSON)

After reviewing the Swiz sample applications and reading the documentation (not a ton of documentation is by design here) I created the following directory structure, simplistic since the app is a POC:



I then needed to tell Swiz where my application resources are located. In my Main.mxml file I added a few namespaces to my Application tag:
  1. xmlns:view="com.nictunney.view.*" - So I can import my base view
  2. xmlns:config="com.nictunney.config.*" - So I can tell Swiz where my config file is located
  3. xmlns:swiz="http://swiz.swizframework.org" - namespace for the Swiz framework
I then declared my Swiz configuration in Main.mxml using the swiz component tags beanProviders and config:
<fx:Declarations>
<swiz:Swiz>

<!-- BeanProviders simply contain the non-display objects that Swiz should process. -->
<swiz:beanProviders>
<config:Beans />
</swiz:beanProviders>

<swiz:config>
<!-- The eventPackages value tells Swiz the path to your Event classes,
and viewPackages is an optional value that speeds up the processing of display classes. -->
<swiz:SwizConfig
eventPackages="com.nictunney.event.*"
viewPackages="com.nictunney.view.*" />
</swiz:config>

</swiz:Swiz>
As you can see from the comments, I point beanProviders to my Beans.mxml configuration file. In this simple example I can put all of my bean configuration data in a single file, but you may have more depending on your architecture.
<swiz:BeanProvider
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:swiz="http://swiz.swizframework.org"
xmlns:model="com.nictunney.model.*"
xmlns:control="com.nictunney.control.*"
xmlns:service="com.nictunney.service.*">

<service:MapService id="mapService" />
<control:MapController id="mapController" />

</swiz:BeanProvider>
As you can see above, I included my service and controller components for my map object (named map since we will be drawing a relationship map). Take a peek in the MapService.as class and you will see loadItems(), which makes an HTTP call to the CouchDB restful interface to retrieve a view (no queries, only document views in CouchDB). The successful result will call the httpResult method in the same class (more on that logic later).

The aptly named MapController.as class serves as a controller interface for the map service. Note that it makes use of the Swiz [Inject] metadata tag. This is clutch as the [Inject] metadata tag is performing a dependency injection by type here (as recommended by the Swiz docs) based on the definition in the Beans.mxml file. We can now reference the current state of the MapService using the mapService pointer (as seen on line 17).

I defined a single custom event for the application. Nothing to note here except that when calling the constructor on the Event superclass, you need to set the 'bubbles' property to 'true' (see line 13 in MapEvent.as). To hold the data there is a single GenericItem class defined. No real magic going on here either.

So, aside from the dependency injection, where else does Swiz get involved in the app? Glad you asked. Again, I feel that event mediation is the primary reason to use a framework in Flex. Code in Flex is pretty self organizing, but events can be a bear across a complex model with multiple views. Swiz handles event mediation well. If you take a peek at Map.mxml (the only view defined for this sample application), aside from the view and function to handle the SpringGrpah itself, there are two things of note handled by Swiz.

First, event mediation really is as simple as the following code:
[Mediate( event="MapEvent.PLACE_ITEM_REQUESTED", properties="item" )]
public function newItem(item:GenericItem): void {
trace('[Swiz] Mediating MapEvent.PLACE_ITEM_REQUESTED for item.' + item.id + '.');
var i: Item = new Item(item.id);
i.data = item;
g.add(i);
if(prevItem != null)
g.link(i, prevItem);
prevItem = i;
s.dataProvider = g;
}
The [Mediate] metadata tag tells Swiz to call the newItem() function when the MapEvent.PLACE_ITEM_REQUESTED event is fired anywhere in our example application. Note that we can use MapEvent directly (and not the package name) since we defined the eventPackages attribute in our swiz config in Main.mxml. Another important point here is the properties property. By telling Swiz to pass in the item property from our event, newItem() can now be called explicitly from elsewhere in our code (see that no event is being passed into the function itself?

The original event is fired from the MapService class when the HTTP call is completed. Two things to note in MapService.as. Since it is not a UI component we need to create an instance of IEventDispatcher and let Swiz know to monitor events passed from it by specifying the [Dispatcher] metadata tag:

[Dispatcher]   public var dispatcher : IEventDispatcher;

This dispatcher is then used to send the events from our service. If we were dispatching an event from a UI component, Swiz would monitor it by default.

The last thing Swiz needs to know is where to start processing our application. For our needs we are telling Swiz to call the main() function in Map.mxml by using the [PostConstruct] metadata tag. [PostConstruct] is called after a display object is placed on the stage. Be sure to check out the Swiz Bean lifecycle management page for more information.

If you run the application in debug mode (make sure you have the debug Flash player) you'll see Flex load the SpringGraph instance onto the stage, Swiz call the main() function, triggering the MapEvent to fire, and newItems() receive the GenericItem objects and add them into the SpringGraph. Pretty sweet!

Source code for this example can be found here