Feel like a geek and get yourself Ema Personal Wiki for Android and Windows

29 September 2009

Inheritance and NHibernate.Search

I recently ran into a problem using NHibernate.Search. It is not possible to query properties of a derived class if NHibernate.Search only has access to it through a base class.
I used to have:
  [IndexedEmbedded]
  public virtual FieldType FieldType
  {
      get;
      set;
  }
The FieldType class is an abstract class from which concrete implementations derive. I wanted to index the properties of several derived classes, for example the OtherFieldType class:
public class OtherFieldType : FieldType {
  [Field]
  public virtual string Name {
      get;
      set;
  }
}
In this example, querying NHibernate.Search with "FieldType.Name:something" won't return any results. Apparently NHibernate.Search does not know it should query the concrete class implementation, OtherFieldType, for this query.

The workaround for this is to remove the IndexedEmbedded attribute from the base property and include a private field dedicated for NHibernate.Search to index and query. The private field does hold the concrete implementation:
  public virtual FieldType FieldType
  {
      get;
      set;
  }

  [IndexedEmbedded]
  private OtherFieldType OtherFieldType
  {
      get
      {
          return FieldType as OtherFieldType;
      }
  }
In this way, NHibernate.Search will know how to index and search the embedded properties. The query "OtherFieldType.Name:something" will now return the correct results.

26 September 2009

Google Chrome plugin for IE - yet another browser platform

The newly released Google Chrome plugin for IE introduces yet another browser platform to be aware of as web developer. We test our websites on IE, FF, Chrome and maybe Safari. Now a new platform is added to the list: IE with a bit of Chrome.

The Google Chrome Frame developers did their best to make it as unobtrusive as possible. The plugin will only kick in if the Google Chrome Frame tag is present on a webpage. But the tag does not guarantee anything. Maybe the website visitor refuses to install the plugin. Maybe the website visitor uses the opt-in list to force your website to use the plugin, although there is no tag present.

So note to self: don't forget to test the website without the plugin if the Google Chrome Frame tag is used. And don't forget to test the website with the plugin enabled although the website does not include the tag.

25 September 2009

Html Agility Pack to the rescue

One of our products is a messaging processor which uses XMl internally. Somehow someone messed up and managed to insert characters into the XML which are not valid, making the message "invalid XML". By the way "Invalid XML" is a contradictio in terminis. I would rather refer to "invalid XML file" as A Text File That Looks A Lot Like XML But Isn't.

Solving the issue would require updating the shared core component which is used by many applications. Updating the core component was not an option as a bugfix.

We decided to fix the bug in the following major release, but still needed a workaround for the problems in the field.

Enter Html Agility Pack. It is a tolerant library that can read HTML files (text files looking a lot like SGML or like XML) and convert them to XHTML. We inserted a processor into the processing chain that XMLlifies the message as it passes the processor, et voilĂ !

24 September 2009

Another client wish

For an internal project (C# / NHibernate / ASP.NET MVC / JQuery) there was a request that users could be able to mark parts of the data with colors to indicate parts of the data have changed.

If I had to incorporate this into my domain model, it would be quite complex. I would have to keep track of statuses of every property of every object, and every action should know which status data is relevant to that particular action.

I decided that this would be a simple solution: the coloring will be purely a user-interface feature. There will be a table in the database with the columns "URL", "ElementId", "Color" to store the coloring data. The userinterface will be querying this data after the page has been loaded and store the data using AJAX calls.

I am not 100% sure about this. It is clearly the simplest solution. But the colors are really statusinfo about the data in the application, while the statusinfo will never be associated with the data, only with user interface elements. But I decided in favor of the UI solution taking into account that
- the coloring data is cursory
- the request is purely a visual one
- the ASP.NET MVC application will be the only user of the data

See if I will regret this later.

23 September 2009

Client wishes

In an application I am working on different clients want different views, depending on the context. For example: client A is a sonographer and wants all ultrasound data on top, client B is an obstetrician and wants all obstetric data on top.

I first thought of a per-user preference which is stored in the database. Unfortunately, I did not have a per-user store mechanism yet, so I would have to develop it. Because I am lazy, this triggered a though: this isn't actually a per-user setting, but a per-role setting. There are clients that are both obstetricians and sonographers. They would want the data ordered differently depending on the role they have at that time.

So I decided to solve this in a very simple way, which the user is going to like. I created a button in the view that only switches view properties when clicked. No server-side code involved. It sets a persistent cookie on the client with the last state. The next time the user visits the particular part of the application, the last state is restored.

22 September 2009

"convenience" back doors

It can be tempting to create "convenience back doors" in code to make short cuts. "Isn't it easier to skip all these layers and just call layer 1 from layer 3?". Yes, it is easier in the short run, but later on it will make refactoring very hard. I think the word "just" in any code-related conversation should set off alarms in your head. Layers are there for a reason.

I am currently involved in replacing a DAL for an existing legacy application. The existing DAL creates SQL statements and passes them to a handler that executes the statements with a connection from a connection pool. My job is to remove the SQL statements and replace them by service calls. Luckily the statements are very simple, because the application once used DBase, which isn't a relational database. So most of the SQL statements don't even use joins. This is of course very inefficient, but in this case my luck.

I started bottom-up, so I abstracted the SQL handler first to be able to monitor what is going through. Secondly i started looking for calls to the SQL handler class. It is a Vb6 application, but there is actually a layered architecture, so I figured that too wouldn't be too hard.

Until i found a function in the application layer. The function was there for "convenience". With the function anyone can throw any SQL statement at the SQL handler. And did i mention ... the function is part of the COM component's public interface.

The point of making classes and functions or, more generally, layers, is to abstract implementation details away from its users.

So much for abstraction.

17 September 2009

Fetchmode.Eager, but still a proxy

I just had an issue where i could not cast a property of type Proxy_blah_blah_blah to the type that it really should have been ("Patient", in this case). The issue was still there after i explicitly set the fetchmode to "Eager": NHibernate seemed to ignore the fetchmode.

In a way, it actually did ignore the fetchmode. I am not sure if this is by design. I did not look this up, but blog the cause for future reference.

The problem was that the objects which were to be loaded eagerly, were already fetched by a previous query which had fetchmode lazy for these objects. So the objects were already present in the current session as proxies. Apparently NHibernate does not re-evaluate the lazyness of the objects if another query wants these objects to be fetched eagerly. I can understand this, because it is impossible to change existing objects to another type + nhibernate obviously wants to return the same objects from the same session.

To summerize the problem:

1. a query loads objects which have a reference to Patient which has a lazy initialized property Person
2. The property Person is now a proxy, in my case the proxy of a base class of Person
3. a second query loads objects that also have a reference to Patient. The query has fetchmodes for associationpath 'Patient' = Fetchmode.Eager and for associationpath 'Patient.Person' = Fetchmode.Eager.
4. Nhibernate now in a way ignores the fetchmode properties: in nhprof the query looks good, but the returned object tree has the previously created proxy objects instead of the resolved objects.
5. Using the Person property as a Person object now fails, because it is a proxy of a base class of Person.

A solution would be to use multiple sessions. The solution i chose in this setup is to eagerly load the objects in the first query, which made sense anyway.

01 September 2009

Throw it away liberally

The code we developers write is like a child. It shouldn't be. The problem with being protective about your own code is that there is a barrier to change it. But the code is bad, contains lots of bugs, or worse, does not fulfill any requirement that it should.

That's why we should be very liberal to throw away code if we need to, especially if it is our own code.

Sourcegear does not add files after having worked online

If you're using the Sourcegear Vault client plugin for Visual Studio and use the feature "work offline", you have probably encountered this problem. If you added file while being offline, the added files won't be added to Vault after you "Go Online". The vault client thus silently corrupts your codebase.

I learned the hard way that i have to open each and every folder where i could possibly have added new files, to manually add them to vault after going online. But lately I discovered a good workaround. You can right-click on the project file, and choose "Add to vault" on the project root. All files that have not been added yet, will be added by that action.

How to get a working Back-button for an AJAX app in Internet Explorer

In an AJAX application, the back-button will take you to the wrong place because in AJAX applications the actions don't update the browser location. There are some solutions that change the hash of the Location (the part behind the #), but those solutions do not work in Internet Explorer.

The problem with IE is that a change in the hash will not lead to an entry in the history, so the back button will take you back to the previous page anyway. IE does react if you change the src attribute of an IFRAME, so most solutions for IE are in the direction of using a hidden IFRAME.

Since I did not find any actually working code, I post it here for future reference. The code works in IE, FF and Chrome.

The main page contains an iframe. The source of the iframe is an actual document on the server (iframe.html). The only thing the iframe document does is echo it's source url back into the parent page location hash:
<html>
 <body>
  <script type="text/javascript">
   function parseLocation() {
    var src = location.href;
    var pos = src.indexOf('href=');
    if (pos === -1)
     src = '' //home
    else
     src = src.substring(pos + 5);
    top.location.href = top.location.pathname + '#' + src;
   }

   parseLocation();
  </script>
 </body>
</html>

The parent page redirects anchor clicks to update the src attribute of the iframe. Because the iframe will be reloaded, IE will update the history of the browser. The iframe writes the src url back into the parent page location. The parent page monitors the location and loads the appropriate url in the appropriate div:
<html>
  <head>
    <title>Ajax test</title>
  </head>
  <body>
    <script type="text/javascript" 
      src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js">
    </script>
    <script type="text/javascript">
      var baseHref = location.protocol + '//' + location.host;
      
      $(document).ready(function() {
        createAjaxLinks();
        setInterval(checkLocationHash, 50);

        $('#trackingframe').get(0).src = iframeSrc + '?href='
          + location.hash.substring(1);
      });
      
      function createAjaxLinks() {
        $('a.' + ajaxLinkClass)
          .removeClass(ajaxLinkClass)
          .click(function(){
            var href = this.href;
            if (href.indexOf(baseHref) > -1)
              href = href.slice(baseHref.length);

            $('#trackingframe').get(0).src = iframeSrc 
              + '?href=' + href;
            return false;
          });
      }
      
      function checkLocationHash() {
        if (location.hash !== this.lastHash) {
          var url = null;
          if (location.hash === '' || location.hash === '#') { 
            //home
            url = initialDocument;
          }
          else {
            var url = location.hash.substring(1);
          }
          if (url !== null) {
            url = baseHref + url;
             $('#siteContainer').load(url, null, createAjaxLinks);
          }
          this.lastHash = location.hash;
        }
      }
      
      var initialDocument = '/1.html'; //absolute url
      var iframeSrc = '/iframe.html';  //absolute url
      var ajaxLinkClass = 'ajaxLink';  //class for ajax links
    </script>
  
    <div id="siteContainer">
    </div>
    <iframe id="trackingframe" style="display:none">
    </iframe>
    
  </body>
</html>
For this example I created three test documents, named 1.html, 2.html and 3.html, which will in turn be loaded in the siteContainer div.

1.html:
<a href="2.html" class="ajaxLink">Load the second document</a>

2.html:
<div>
 This is the second document. 
 <a href="3.html" class="ajaxLink">Load the third</a>
</div>

3.html:
<div>Third document</div>

This example loads all links with class "ajaxLink" into the "siteContainer" div. In real life, you would probably want more control over in which div the link will be loaded. This can be accomplished by including the "target" in the class somehow and parse the class of the link to find this target.