# Tuesday, November 28, 2006

See comments...

/**
* Iterates through all mapped Hibernate classes and attempts to select
* all for that table/class pair. If this test does not fail then this
* indicates that the hibernate mappings at the very minimum match the
* database schema.
*/

@Test
public void allHibernateMappingsWork()
{
    Configuration configuration = new Configuration();
    configuration.setProperty(Environment.SHOW_SQL, "true");
    
    SessionFactory sessionFactory = configuration.configure().buildSessionFactory();
    Session session = sessionFactory.openSession();
    
    Map metaData = sessionFactory.getAllClassMetadata();
    for (Iterator i = metaData.values().iterator(); i.hasNext();)
    {
        EntityPersister persister = (EntityPersister) i.next();
        String className = persister.getClassMetadata().getEntityName();
        String qry = "from " + className + " c";
        List result = session.createQuery(qry).list();
        assertTrue("No results for " + className, result.size() > 0);
    }
    
    session.close();
}

Tuesday, November 28, 2006 9:37:44 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, November 19, 2006
To turn on the touch screen feature of an emulator, go into C:\WTK25\wtklib\devices\[device]\ and open up the [device].properties file.  Set: touch_screen=true.

Sunday, November 19, 2006 2:20:40 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 
# Friday, November 17, 2006
JXPath looks pretty useful.  It provides XPath syntax to query your POJOs - very similar to LINQ.

Friday, November 17, 2006 5:25:17 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, November 11, 2006
I'm in the middle of researching platforms to put together a speaking assitance program for my daughter who can only vocalize a handful of words.  It must be programmable (C++, C#, or Java), have a touch screen, and have audio capabilities.

Possible platforms:

1. Nintendo DS
2. Windows Mobile w/NET compact framework
3. Java ME (formerly J2ME)

Currently I'm leaning towards Java ME since I now work with Java at work and that seems to have the greatest market penetration.  It looks like the Palm Z22 may work, it seems to have a J2ME implementation and is cheap ($99).

Mentions IBM's J2ME for the Z22 http://blog.tmcnet.com/blog/tom-keating/technology-and-science/palm-tx-and-palm-z22-handhelds.asp\

Palm Z22 specs: http://www.palm.com/us/products/handhelds/z22/specs.epl

Intro to J2ME with a Palm device: http://www.devx.com/wireless/Article/31092

Java ME home: http://java.sun.com/javame/index.jsp

Looks like I'll need this installed on the Palm device: IBM WebSphere Everyplace Micro Environment for Palm OS Garnet (WEME) provides a MIDP2.0/CLDC 1.1 compliant run-time: http://www-306.ibm.com/software/wireless/weme/

Saturday, November 11, 2006 9:16:18 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, November 03, 2006
I just installed P4Report, which basically gives you ODBC access to your Perforce depot - pretty cool.  I can now whip out a status report for the week:

select user, description, date from changes where user in ('joe', 'dave') and timestampdiff(4, date, curtime()) < 7 and P4OPTIONS='longdesc' order by user, date;

Friday, November 03, 2006 7:32:14 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
I don't hate Java, it's certainly leaps and bounds over Visual Basic and in a lot of ways C++, but after working in C# 2.0 for the past year...  Eck!

Things I wish Java had:
  • Better generic support - no erasure (screw backwards compatibility, do it right)
  • Operator overloading
  • Properties
  • Partial classes

There would much more to hate if I wasn't using Java 5.0.  Apparently autoboxing, something I take for granted in .NET, just got added to Java in the last release.

Friday, November 03, 2006 7:30:03 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, October 21, 2006
Since I took the day off to prepare for our family cruise to Mexico tomorrow, I ran into an extra hour today to do with as I please.  Having wanted to play around with Atlas (now ASP.NET AJAX) and Castle ActiveRecord for a while, why not cram them both into my free hour today.  So I did exactly that, and I still have 10 minutes to spare to write this blog entry - and that includes the downloading of the software, installation, and reading some of the docs.  Although it has become painfully obvious to me that I need a new PC as I think I wasted a good 5 to 10 minutes waiting for my PC to do "stuff."

I was amazed at how dumb foundingly easy both these technologies make it to throw together a featureful web app.  First I created a database table:

CREATE TABLE GalleryUser (
    GalleryUserId            int IDENTITY(1, 1) PRIMARY KEY,
    FullName                varchar(50) NOT NULL,
    Login                    varchar(16) NOT NULL,
    CreatedDate                smalldatetime NOT NULL DEFAULT GETDATE()
)

then I went about creating a GalleryUser class marked up with ActiveRecord attributes.  The attributes mapped my class properties to the table I just created above.

using System;
using Castle.ActiveRecord;

namespace Sneal.Gallery.Core
{
    [ActiveRecord("GalleryUser")]
    public class GalleryUser : ActiveRecordBase
    {
        private int id;
        private string fullName;
        private string login;
        private DateTime createdDate;

        public GalleryUser() { }

        [PrimaryKey(PrimaryKeyType.Native, "GalleryUserId")]
        public int Id
        {
            get { return id; }
            set { id = value; }
        }

        [Property("FullName")]
        public string FullName
        {
            get { return fullName; }
            set { fullName = value; }
        }

        [Property("Login")]
        public string Login
        {
            get { return login; }
            set { login = value; }
        }

        [Property("CreatedDate")]
        public DateTime CreatedDate
        {
            get { return createdDate; }
            set { createdDate = value; }
        }

        public static GalleryUser[] FindAll()
        {
            return (GalleryUser[])FindAll(typeof(GalleryUser));
        }

        public static GalleryUser Find(int id)
        {
            return (GalleryUser)FindByPrimaryKey(typeof(GalleryUser), id);
        }
    }
}

Next I created a Global.asax to handle my ActiveRecord initialization and NHibernate session per request schtuff.  This particular part (including my web.config mods) is where I spent the bulk of my time with ActiveRecord.

using System;
using System.Web;
using System.Web.Security;
using System.Configuration;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;
using Sneal.Gallery.Core;

namespace Sneal.Gallery.WebUI
{
    public class Global : System.Web.HttpApplication
    {
        public Global()
        {
            this.BeginRequest += new EventHandler(Global_BeginRequest);
            this.EndRequest += new EventHandler(Global_EndRequest);
        }

        protected void Application_Start(Object sender, EventArgs e)
        {
            IConfigurationSource source = ConfigurationSettings.GetConfig("activerecord") as                      IConfigurationSource;
            ActiveRecordStarter.Initialize(source, typeof(GalleryUser));
        }

        public void Global_BeginRequest(object sender, EventArgs e)
        {
            HttpContext.Current.Items.Add("nh.sessionscope", new SessionScope());
        }

        public void Global_EndRequest(object sender, EventArgs e)
        {
            try
            {
                SessionScope scope = HttpContext.Current.Items["nh.sessionscope"] as SessionScope;
                if (scope != null)
                {
                    scope.Dispose();
                }
            }
            catch (Exception ex)
            {
                HttpContext.Current.Trace.Warn("Error", "EndRequest: " + ex.Message, ex);
            }
        }

    }

}

Now for the fun ASP.NET AJAX hookup in my ASPX page.  This is where all of the AJAX magic happens, specially in the Update Panel.  I could have thrown all of the controls into the UpdatePanel and then I wouldn't have needed to add the explicit AsyncPostBackTrigger reference, but hey - I wanted to see how it works.  Having used Telerik's AJAX framework, which is quite good by they way, I found the ASP.NET AJAX framework even easier.  It's so well integrated now into ASP.NET and Visual Studio, I can't imagine anyone not using it going forward.  It won't be cool to use AJAX next year, it will just be the de facto standard.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>ASP.NET AJAX Test Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:ListBox ID="lstUsers" runat="server" />
            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="btnGetUsers" />
            </Triggers>
        </asp:UpdatePanel>
        <asp:Button ID="btnGetUsers" runat="server" Text="Get users from DB"
            OnClick="btnGetUsers_Click" />       
        <asp:TextBox ID="txtInfo" runat="server" EnableViewState="false" />           
    </form>
</body>
</html>

And the associated code behind, which looks just like it would without the AJAX magic.  The fun part to note here is the data fetching; just too easy!  So easy in fact I just skipped following any decent application patterns like MVP, but hey its just a tech spike.

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using Sneal.Gallery.Core;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
            txtInfo.Text = "IsPostback = true";
        else if (IsCallback) // doesn't work as hoped.
            txtInfo.Text = "IsCallback = true";
        else
            txtInfo.Text = "Initial page load = true";
    }

    protected void btnGetUsers_Click(object sender, EventArgs e)
    {
        GalleryUser[] users = GalleryUser.FindAll();

        foreach (GalleryUser user in users)
        {
            lstUsers.Items.Add(user.FullName);
        }
    }
}

In the end, I'm very happy with the results.  And to my surprise my spike app worked on the first run.

My only issue is that I'm not sure I like ActiveRecord and its static data access methods on the actual objects.  It seems like it's crossing the boundaries of separation of concern, but then again it didn't cost me any coding time...  I'll have to think about it.

Friday, October 20, 2006 11:23:08 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, October 20, 2006
My ducked taped together photo site was causing me issues.  I finally fixed it...  I was getting a strange GDI+ exception, amongst others, when trying to use the site.  Apparently my NTFS permissions to the media folder got mucked up, so I ended up having to take ownership of all the files and then grant the NETWORK SERVICE account write permissions to the folder.

I think this happened before a long time ago.  I'm now thinking I don't like the thumbnails and xml files in each of the sub folders where the actual full size photos are stored.  It seems better to index these in a central location - heck maybe even use a database. 

Hmm...  Sounds like an excuse to play around with some new tech.

Friday, October 20, 2006 4:21:07 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, October 11, 2006
I came across this snippet of javascript in one of our apps...

if(i == 0 || i == 2 || i == 3 || dirty == ''){
//had to do this weird workaround as i!=0 was not working
}

WTF
Wednesday, October 11, 2006 6:00:44 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, October 10, 2006

OK, you’ve finally built up your beautiful platform agnostic and persistent ignorant business domain layer.  It solves all of your business requirements and is elegant and maintainable – too bad the model doesn’t fit nicely into your user interface!

This is about the time a non-domain driven developer says, “ha, I told ya that domain model was a waste of time!  You should have modeled your objects after the user interface!”  Was it really a waste of time?  Of course not!  Well then how do we slap a UI on top of a domain model?  Chapter 11 of Jimmy Nilson’s Applying Domain-Driven Design and Patterns to the rescue.

Basically you have three options when hooking up a user interface to your domain model:

  1. The domain model hooks up directly to the UI, and it just happens to be a good fit.
  2. You wrap the domain model with a presentation specific object.
  3. You map data from the domain model to a presentation specific object.

Of interest here are options 2 and 3.  To keep the domain model clean and pure, it may make sense to create a presentation specific object that transforms a domain specific object into a user interface friendly one.  The example given in Jimmy’s book is the one where the domain model represents a name, first and last, as separate fields.  In the UI, the first and last names are placed together in a single textbox. 

Below I’ve provided an example of option #2, wrapping.  In this example ResourceWrapper in the presentation layer wraps a domain model Resource object.  One thing that makes the UI easier to work with is to flatten out object graphs like in this ResourceWrapper example, specifically the resource’s manager.

 

public class ResourceWrapper
{
    private Resource resource;

    public ResourceWrapper(Resource resource)
    {
        this.resource = resource;
    }

    public string Name
    {
        get { return resource.FirstName + " " + resource.LastName; }
        set
        {
            string[] names = value.Split(" ".ToCharArray(), 2);
            resource.FirstName = names[0];
            resource.LastName = names[1];
        }
    }

    public string ManagerName
    {
        get { return new ResourceWrapper(resource.Manager).Name; }
        set { new ResourceWrapper(resource.Manager).Name = value; }
    }

    public decimal Salary
    {
        get { return resource.Salary; }
        set { resource.Salary = value; }
    }

    public Resource GetDomainObject()
    {
        return resource;
    }
}

I have to write more code?  Yes, but you may be able to get around a lot of this by creating a generic object to object framework that sets properties via reflection and/or code generation.  In the end, wrapping or mapping domain objects sounds like a good idea when they just won’t fit nicely into the UI.

Tuesday, October 10, 2006 4:57:09 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  |