Lamino, or What the Heck Do I Know About Dependency Injection

Recently, someone asked me if I knew what Dependency Injection was. Well, Dependency Injection and I go way back, I have to say. Or Inversion Of Control. Or whatever it was called at the time, I can’t remember. The time, however, was shortly after the turn of the centrury. Enter nostalgic guitar, please.

I was working at Velti, building a system for SMS interactions. Not content with the state of configuration management, I had developed a rudimentary facility to instantiate objects and set their properties. Today, you’d call it a DI/IoC container. Because reinventing the wheel is always fun, but not always productive, as we were growing this facility I was looking around for other similar stuff and for people with similar ideas. There weren’t any, except for Rod Johnson and his book “Expert one-on-one J2EE design and development” describing something called Interface21. But it was enough. The approach Rod was describing was very much to my liking. I immediately switched the XML grammar to that of what came to be known as Spring and adopted most of its concepts.

However, I did not switch to Spring, because it lacked two things, both of which we had come to rely upon.

  • One of them was the ability to separate the DI part from the instantiation part. We were using XmlWeb2, which I might blog about someday, which was instantiating MVC actions and views using a reloading classloader, so we needed these two phases to be separate. (BTW, it’s very easy to write a reloading classloader in Java, once you realize the following: a classloader can never reload a class!).
  • The other was a mechanism to build configuration in layers. It it mostly the latter that the rest of this post will be occupied with. Or rather its descendant, which is Lamino.

Lamino

The blurb: Lamino is a high-level configuration metalanguage that enhances basic IoC (Inversion of Control a.k.a. Dependency Injection) with configuration layering and encapsulated components. It is hosted by an IoC language and it “compiles” to it. Using configuration layering, the application developer can create editions or extensions by expressing the differences of each configuration layer from the layer below it. Using encapsulated components, the application developer can define reusable configuration chunks that import and export specific services, while hiding internal contents.

You should understand that, in my puritan mind, there is no program structure outside of the configuration. The whole object graph of the singletons that comprise the logic layer, should be there. That object graph and the collaborations it describes is the application. Configuring a different edition or deployment can involve a lot more than modifying some properties. A whole portion of the object graph could need be redefined. That’s why relying on a separate layer of property files, or something, can only be half a solution. And doing a different build of a system just to change how some classes collaborate, is not a solution at all.

I will not replicate the information in the project Web site here. But I will show you what Lamino does by walking you through the examples in the distribution, which is not covered by the site. They are the same for all three containers covered (you’d better get the latest files from SVN (here, the DotNet distribution), by the way, because the WebContextHandler for .Net is only to be found there). WordPress insists on mangling large XML snippets containing “object” elements, so you’ll have to view the files from there.

Example

To cut a long story short the resulting system can be found in Derived-derived.xml, which is the actual output of Lamino. To make the point that Lamino is purely transformation and did not need a full-blown programming language to implement it, it is written in XSLT (which, BTW, is the first mainstream functional language).

Modify an object with extends=”extends”

Let’s have a look at object “ObjectToBeExtendedFromMoreBase”, keeping in mind that element “x-object” is really “object” but I had to rename it to keep WordPress from slurping it.

This object is defined in MoreBase.xml:

	<x-object id="ObjectToBeExtendedFromMoreBase">
		<property name="PropertyToBeCopiedAsIs" value="foo"/>
		<property name="PropertyToBeReplaced" value="value to be replaced"/>
		<property name="PropertyToBeRemoved" value="foo"/>
		<property name="PropertyToBeAppendedTo">
			<list>
				<value>val1</value>
				<value>val2</value>
			</list>
		</property>
		<property name="PropertyToBePrependedTo">
			<list>
				<value>val1</value>
				<value>val2</value>
			</list>
		</property>
	</x-object>

And extended in Base.xml using extends=”extends”.

	<x-object id="ObjectToBeExtendedFromMoreBase" extends="extends">
		<property name="NewProperty" value="foo2"/>
		<property name="PropertyToBeReplaced" combine="replace" value="new value"/>
		<property name="PropertyToBeRemoved" combine="remove"/>
		<property name="PropertyToBeAppendedTo" combine="append">
			<list>
				<value>newval1</value>
				<value>newval2</value>
			</list>
		</property>
		<property name="PropertyToBePrependedTo" combine="prepend">
			<list>
				<value>newval1</value>
				<value>newval2</value>
			</list>
		</property>
	</x-object>

The resulting configuration is the following. Note that I couldn’t coerce either MSXML or Xalan to produce whitespace to my liking, so no whitespace remains in the output. Lamino annotates the output with some comments to make it easier to trace the output.

<!--Extended-->
<x-object id="ObjectToBeExtendedFromMoreBase" scope="application" visibility="public" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default">
<property name="NewProperty" value="foo2"></property>
<!--Replaced-->
<property name="PropertyToBeReplaced" value="new value"></property>
<!--Property PropertyToBeRemoved was removed-->
<property name="PropertyToBeAppendedTo">
<list>
<!--Original elements-->
<value>val1</value>
<value>val2</value>
<!--Appended elements-->
<value>newval1</value>
<value>newval2</value>
</list>
</property>
<property name="PropertyToBePrependedTo">
<list>
<!--Prepended elements-->
<value>newval1</value>
<value>newval2</value>
<!--Original elements-->
<value>val1</value>
<value>val2</value>
</list>
</property>
<property name="PropertyToBeCopiedAsIs" value="foo"></property>
</x-object>

Property “NewProperty” is added in Base.xml.

Property “PropertyToBeReplaced” starts off with value=”value to be replaced”, but this value is overriden using combine=”replace” in Base.xml with value=”new value”, which is the value that remains in the end.

Property “PropertyToBeRemoved” is removed using combine=”remove” in Base.xml.

Property “PropertyToBeAppendedTo” contains two elements to begin with, and two more are added in Base.xml using combine=”append”. A similar modification is done to property “PropertyToBePrependedTo”, where two elements are prepended using combine=”prepend” in Base.xml.

Finally, property “PropertyToBeCopiedAsIs” is not modified at all.

Replace an object with extends=”overrides”

Let’s focus now on object “ObjectToBeReplacedFromMoreBase”.

	<x-object id="ObjectToBeReplacedFromMoreBase">
		<property name="Property2" value="bar to be replaced"/>
	</x-object>

Things are simpler in this case, as this object is overriden in Base.xml.

	<x-object id="ObjectToBeReplacedFromMoreBase" extends="overrides">
		<property name="Property2" value="new value"/>
	</x-object>

The resulting object is, indeed, what Base.xml prescribes.

<!--Overriden-->
<x-object id="ObjectToBeReplacedFromMoreBase" scope="application" visibility="public" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default">
<property name="Property2" value="new value"></property>
</x-object>

Importing components

Now, let’s look how one can define DI components. Derived.xml imports the same component twice.

	<import resource="Component.xml"/>
	<import resource="Component.xml">
		<hiding object="OtherPublicComponentToBeHidden"/>
		<renaming object="ExplicitlyPublicComponent" as="Compo1"/>
		<renaming object="ImplicitlyPublicComponent" as="Compo2"/>
		<providing object="NewObject" as="External"/>
	</import>

Note that the component itself employs configuration inheritance in its definition.

ComponentBase.xml:

<x-objects xmlns="http://www.springframework.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
lamino-objects.xsd">
	<x-object id="ExplicitlyPublicComponent" visibility="public">
		<property name="Property3" value="foobar original"/>
		<property name="Property4">
			<ref local="Hidden"/>
		</property>
	</x-object>
	<x-object id="ImplicitlyPublicComponent">
		<property name="Property6" value="foobaz original"/>
		<property name="Property7" ref="External"/>
	</x-object>
	<x-object id="OtherPublicComponentToBeHidden"/>
	<x-object id="Hidden" visibility="private">
		<property name="Property5" value="baz original"/>
	</x-object>
</x-objects>

Component.xml:

<x-objects xmlns="http://www.springframework.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.net
lamino-objects.xsd" extends="ComponentBase.xml">
	<x-object id="ExplicitlyPublicComponent" visibility="public" extends="extends">
		<property name="Property3" value="foobar" combine="replace"/>
	</x-object>
	<x-object id="Hidden" visibility="private" extends="extends">
		<property name="Property5" value="baz" combine="replace"/>
	</x-object>
</x-objects>

As you see, the first importing does not specify anything in particular, while the second importing specifies the following.

  • Object “OtherPublicComponentToBeHidden” is to be hidden.
  • Objects “ExplicitlyPublicComponent” and “ImplicitlyPublicComponent” are to be renamed.
  • Object “NewObject” is to replace references to object “External”.

The effects of these (and the comparison to the unmodified component import) is seen in the output.

<x-object id="ExplicitlyPublicComponent" scope="application" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default">
<property name="Property3" value="foobar"></property>
<property name="Property4">
<ref local="Hidden-IDAQJLVIDASJLV"></ref>
</property>
</x-object>
<x-object id="ImplicitlyPublicComponent" scope="application" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default">
<property name="Property6" value="foobaz original"></property>
<property name="Property7" ref="External"></property>
</x-object>
<x-object id="OtherPublicComponentToBeHidden" scope="application" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default"></object>
<x-object id="Hidden-IDAQJLVIDASJLV" scope="application" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default">
<property name="Property5" value="baz"></property>
</x-object>
<x-object id="Compo1" scope="application" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default">
<property name="Property3" value="foobar"></property>
<property name="Property4">
<ref local="Hidden-IDAKJLVIDASJLV"></ref>
</property>
</x-object>
<x-object id="Compo2" scope="application" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default">
<property name="Property6" value="foobaz original"></property>
<property name="Property7" ref="NewObject"></property>
</x-object>
<x-object id="OtherPublicComponentToBeHidden-IDAXDEUIDAYDEU" scope="application" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default"></object>
<x-object id="Hidden-IDAKJLVIDASJLV" scope="application" dependency-check="default" singleton="true" abstract="false" lazy-init="default" autowire="default">
<property name="Property5" value="baz"></property>
</x-object>

Note that the “visibility” attribute, meant to be used inside components, specifies whether the object will be publicly visible in the output. Hiding is done via a simple renaming of IDs (here, to “Hidden-IDAQJLVIDASJLV” and “Hidden-IDAKJLVIDASJLV”).

Importing
The component expects to find a reference to object “External”. The first importing does not modify this specification and resolution to that reference is done using object “External” defined in Derived.xml. Note that Lamino does not try to verify the validity or even the syntax of the configuration. If object “External” was a broken reference, it would stay a broken reference.

The second importing modifies the reference to demand an object named “NewObject”, also defined in Derived.xml. Same caveat as before regarding validity of references.

Exporting and Hiding
The component exports all objects that are explicitly or implicitly public. These are objects “ExplicitlyPublicComponent”, “ImplicitlyPublicComponent” and “OtherPublicComponentToBeHidden”, exporting with these names by the first, unmodified, importing. The second importing renames the first two objects and hides the third one. Had it not hidden it, the resulting configuration would contain two objects with the same ID, which would be… inconvenient but, as I have said, Lamino does not check your Spring.Net grammar and syntax (same for Spring for Java and Castle Windsor).

Embedding in Web.config

As my latest jobs where in .Net shops, I have paid particular attention to the Spring.Net distribution. In the latest code to be found in SVN, there is a WebContextHandler to help integrate Lamino in a Web application, in a context to be used instead of the one Spring.Net provides.

using System;
using System.Collections.Generic;
using System.Xml.Xsl;
using System.Linq;
using System.Web;
using Spring.Context;
using WCH=Spring.Context.Support.WebContextHandler;

namespace Lamino.Spring
{
    public class WebContextHandler : WCH 
    {
        protected override IApplicationContext InstantiateContext(IApplicationContext parent, object configContext, string contextName, Type contextType, bool caseSensitive, string[] resources)
        {
            var newResources = LaminoExtend(resources);
            return base.InstantiateContext(parent, configContext, contextName, contextType, caseSensitive, newResources);
        }

        protected string[] LaminoExtend(string[] resources)
        {
            var httpServerUtility = HttpContext.Current.Server;
            XslCompiledTransform transform = new XslCompiledTransform();
            XsltSettings xsltSettings = new XsltSettings();
            xsltSettings.EnableDocumentFunction = true;
            transform.Load(httpServerUtility.MapPath("~/lamino-objects.xslt"),xsltSettings,null);
            var newResources = (string[])resources.Clone();
            for (int i = 0; i < newResources.Length; i++)
            {
                var finalResource = newResources[i] + ".Lamino";
                var resourceFile = httpServerUtility.MapPath(resources[i]);
                var finalResourceFile = httpServerUtility.MapPath(finalResource);
                if (!System.IO.File.Exists(finalResourceFile) || System.IO.File.GetLastWriteTime(finalResourceFile).CompareTo(System.IO.File.GetLastWriteTime(resourceFile)) < 0)
                {
                    transform.Transform(resourceFile, finalResourceFile);
                }
                newResources[i] = finalResource;
            }
            return newResources;
        }
    }
}

You can be up and running with layered and componentized DI in no time!

Configuration layering

I want to see configuration layering become standard practice. It seems to me that any program meant to be deployed in various editions and deployments can benefit from having to specify just the delta from the base. The layers can be, for example: the core, interface-less part of the application, the different embodiments of the application in specific user interfaces and particular deployments. I would be thrilled if Spring and Spring.Net implemented these concepts themselves but, until they do, I offer Lamino as a lightweight solution to that need but, most of all, I intend it to demonstrate the need itself by showing you how easy it can be.

Advertisements

One thought on “Lamino, or What the Heck Do I Know About Dependency Injection

  1. Pingback: Spring break | dsouflis

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s