Mike Nichols - Son of Nun Technology

September 2007 Entries

Edible

Thanks to Billy McCafferty I am now posting edible blogs on devlicio.us.  My new blog url is http://devlicio.us/blogs/mike_nichols and please update any rss to http://feeds.feedburner.com/MikeNichols .

This site will still be up (but this blog not posted to) since my family blog  shares a spot there and Chaya is my daughter whose chronicles continue.

Please come over to devlicio.us and have a snack...there's an active community over there.

 

 

 

Burn Me

Please note my change in RSS to my feedburner account at http://feeds.feedburner.com/MikeNichols .
Should have happened long ago I know...

'could not interpret type' NHibernate exception

This was a beast to track down. Formerly I had implemented ILifecycle on my Domain superclass and everything worked great. After some refactoring however I decided to remove ILifecycle and got this exception

NHibernateMappingException 'could not interpret type Contact, Core.Contact'

This made no sense. In fact I wasn't using ILifecycle callbacks anywhere so why would I suddenly be required to implement this on my entities? I finally tracked this to the ClassBinder in NHibernate where it attempts to infer a type from the TypeFactory.HeuristicType(x) method, passing in the correctly parse class name 'Contact, Core.Contact'.  Now what made this so difficult was that this was an attempt to load a type for a <map> element's <index> (key), where I was using a Contact for a key of a collection.

Since my entity had implemented ILifecycle, this bit of code would allow me to use my entity as a key in a dictionary (from TypeFactory.HeuristicType):

 

                    else if (typeof(ILifecycle).IsAssignableFrom(typeClass))

                    {

                        type = NHibernateUtil.Entity(typeClass);

                    }

I was basically 'cheating' without knowing it by implementing ILifecycle . I think it would be best practice to create a NHibernate IUserType for my Contact class to be able to use it as a key in a dictionary or use the <index-many-to-many> element. It has been some time since I checked this corner of my codebase and apparently my tests are insufficient or else I would have caught this.

So the bottom line is this...if you are receiving this error, check your collection mappings referencing the class in question; especially if they are used as indices for dictionaries.

FIX: SQLiteException , 'no such table'

While using the System.Data.SQLite ADO.NET Provider for NHibernate I kept getting an SQLiteException : 'no such table : [EntityName]' . This isn't an NHibernate bug. SQLite couldn't find the database. I found info here and here where the keyword |DataDirectory|  (using the pipes) should be prepended to the database name. So my new connection string is "DataSource=|DataDirectory|inmemory.db;Version=3;New=True;"  SQLite will try to find the db and if it can't will use the directory where it is running, as it should. Be careful not to have funny characters like colons in the database name or else it still bombs.

After this fix I don't get this error anymore.

Member Plurality In Objects

I always wondered what to call a set of members in an object...after all 'properties', 'fields', and so on are such BORING names. Therefore I was delighted when I came across this quote in ThoughtWorks' ObjectMother document:


ObjectMother might contain a gaggle of the following ... methods:

Did he say GAGGLE ? That's perfect ! I often wondered at the migratory patterns found inside my business objects.

Holy Grailing Redux - The African Swallows of Equal Columns Using Javascript/Prototype

On my current Monorail project I am using the Holy Grail layout I mentioned here . The javascript I modified for this worked just fine but I wanted to be able to keep an element in the bottom right corner of almost every page showing a dynamic contact email.

My first thought was to place a negative margin-top on the footer, nudging the floated element into the content area...kind of an illusion for placement. The problem is, the script places the columns over the area even with z-indices set.

So, I needed to attach an event to my CSSColumns javascript so that I could use the calculated 'height' to apply to the 'top' style attribute of my absolutely positioned element (nested in a relative element).

Here's the content markup snippet:

<!--BEGIN #content -->
                <div id="content">                    
                        
                    <!--BEGIN #c1-->
                        <div id="c1" class="column">
                            ${ChildOutput}
                        <!--END #c1-->
                        </div>
                        
                        <!--BEGIN #c2-->
                        <div id="c2" class="column">   
                            ${?imageboxout}
                            ${?leftcontent}
                        <!--END #c2-->
                        </div>                        
                        <!--BEGIN #c3-->
                        <div id="c3" class="column"><!--position:relative;-->
                           ${?rightcontent}                            
                            <div id="bottom-right"><!--position:absolute;-->
                                ${?bottomright}
                            </div>
                        <!--END #c3-->
                        </div>                 
                 <!--END #content-->

 

One interesting problem: I was using variable length arguments to pass to my object accepting any number of element ids to modify at pageLoad. But I wanted to use an inline {option:value} syntax. How will this work since I am not passing in a 'options' parameter? The code below shows my solution. Works great and is extensible for future options (unlike the previous incarnation):

 

/*Adapted from http://www.thewatchmakerproject.com/journal/308/equal-height-boxes-with-javascript
fixing IE7 compatibility issues and using prototype.js loaded first*/

/*COMMON USAGE:
    In the head element...
    
        <script type="text/javascript">    
            var setBottomRightDiv = function(maxHeight){
                var h = (maxHeight - 60).toString();
                $('bottom-right').setStyle({'top': h + "px"});
            };
            var col = new CSSColumns('content','c1','c2','c3',{onColumnsSet:setBottomRightDiv});
            
            FastInit.addOnLoad(function() { col.equalise(); });                              

        </script>
    >>Where 'bottom-right' might be an element you want to position based on the maxHeight calculation.
    >>'content','c1','c2','c3' are column (div) container ids. Any number of column ids may be passed in.
    >>The last argument may be for 'options'. Here, the onColumnsSet delegate to fire upon setting.
    >>attach CSSColumns 'equalise' method to the page's onload event. (Here, using FastInit).
*/
CSSColumns = Class.create();
Object.extend(CSSColumns.prototype,{    
    maxHeight: 0,
    elIds: new Array(),
    els: new Array(),
    initialize: function(){
        for(var i=0;i<arguments.length;i++)
        {
            if(!(arguments[i] instanceof Object)){
                this.elIds.push(arguments[i]);
            }
            else{
                this.options = { 
                    onColumnsSet: Prototype.emptyFunction
                };
                Object.extend(this.options,arguments[i] || {});           
            }
            
        }               
    },      
    setEls: function(){        
        for (var i=0;i<this.elIds.length;i++) if (!$(this.elIds[i])) return;
        
        for(var i=0;i<this.elIds.length;i++)
        {
            this.els.push($(this.elIds[i]));
        }       
    },
    setOptions: function(options){
         
    },     
    equalise: function(){
        this.setEls();
        this.maxHeight = this.calcMaxHeight();
        for(var i=0;i<this.els.length;i++){
            this.els[i].style.height = this.maxHeight + "px";            
            
        }
        this.notify('onColumnsSet',this.maxHeight);        
    },    
    calcMaxHeight: function(){
        var h = 0;
        for(var i=0;i<this.els.length;i++)
        {
            if(this.els[i].getHeight()>h)
            {
                h=this.els[i].getHeight();
            }
        }
        return h;
    },  
    notify: function(event_name){
        if(this.options){
            (this.options[event_name])
                return [this.options[event_name].apply(this.options[event_name],$A(arguments).slice(1))];
        }
    }
});

if(typeof(Object.Event) != 'undefined')
    Object.Event.extend(CSSColumns);

Now my element ('bottom-right') is found just where it should be on every page!

Microsoft Keyboard Functions

Quick note to point to this post that helped me with intellitype pro. F Lock needs to be off to disable the annoying features of Intellitype keyboards.

I wish keyboards would leave alone function keys in their software.