April 2005 - Posts

[Follow-up on ‘IOC2: Enabling SOA-like services on non-enterprise scale projects.’]


Instantiation of types is usually done by the runtime. In code, you instruct the runtime to make a new instance out of a given type using the new operator and the expression evaluates into a new instance. Leaving the instantiation logic over to the runtime limits an implementer to put initialization logic in the type’s constructor.

 

In the .net framework there is no way to override the runtime’s default behavior of type instantiation. You can’t return your own instances from a class constructor; there is no way to manage an instances lifecycle from within a constructor.

 

Solving the lifecycle problem usually is done by implementing a Singleton pattern in your classes design and disabling the constructor for external use. I’d like to introduce the concept of a ‘Container’ to manage lifecycle support and add some other (less known) patterns enabled by encapsulating type instantiating.

 

 

A Container can be looked at as a generic object factory. It encapsulates the frameworks behavior of instantiating types. Types that you wish should be controlled in such a way can be added to a Container. Instances can be consumed through a container by calling a generic ‘CreateInstance’ method. Here I called the method ‘CreateService’; I’ll stay in a SO A&D mode and continue to call instances served by the Container as ‘services’.

 

Patterns enabled by encapsulating the runtime’s instantiation of services:

(code snippets refer to previous post)

 

Singleton pattern

When service definitions are added to the container (either from configuration or code) the service definition should contain information on how the services lifecycle is managed. When services are marked as ‘static’ it is the Containers job to cleanup the services when its own finalization occurs.


/*done from configuration*/
Container.AddService(

typeof(ITinyTextService),

typeof(ResourceTinyTextService),

LifeCycle.Static);

 

 

Dependency injection pattern

Services that are contained by the same container could be automatically wired into each other by exposing fields or constructor arguments. When using interface types to identify services, the type of a field or constructor argument sets up the requirements that should be met for the container when wiring a service.

class DefaultLoginFunctionality

{

      //constructor params are injected by the container this class belongs to

      //if no service of the given type is available null is passed.

      public DefaultLoginFunctionality(

ITinyTextService resourceManager,

ILogWriterService errorLogger)

      {

            _resourceManager = resourceManager;

            _errorLogger = errorLogger;

      }

}

 

Configuration injection pattern

Services that require configuration can expose configuration values as fields or constructor arguments in order for the container to inject configuration values private to the service instantiated.

public class ResourceTinyTextService

{

      public ResourceTinyTextService(

string baseName,

string assemblyName)

      {

            if (baseName == null)

            throw new ConfigurationException("baseName not defined in configuration");

           

            /*...*/

      }
}

 

Aspect weaving pattern

When a Container allows aspect to be added, these could be mixed with service implementations prior to returning the service.

 

public class ResourceTinyTextService

{

      [Cacheable(VaryByParam="*")//attribute recognized by caching aspect.

      string ITinyTextService.GetText(string key, CultureInfo culture)

      {

            return _resourceManger.GetString(key, culture);

      }

}

 

 

/*done from configuration*/

Container.AddAspect(

typeof(CachingAspect));

 

Containers work from configuration and behavior and availability of services usually depends upon the programs environment (think of development environments/ testing/ staging/ production). Also because the behavior of a Container can be configured, behaviors could change runtime.

 

With the configurations flexibility described above (and good tooling to manage configuration) in mind you could consider the following scenarios:

 

  1. When developing web applications your development environment might not have the need for logging and exception management the production environment does. These services could be coded against, though only be available in a production environment

 

  1. On a production environment you might want to cache a methods output. If this is something that you would not like it to do on your development machine (or left this concern out of your programs design until load increases) a caching aspect could be loaded into your production server’s configuration later on.

 

  1. When a sysadmin encounters unexpected behavior on one of the servers he could configure the environments configuration to log more verbose output in order to collect debug information.

 

I use regular expressions pretty often, in most of the scenarios to validate user input.

 

But let’s say you wrote a regular expression to filter content from html documents.

In a scenario like this it is pretty easy to resort to using character classes like \w for word characters or \d for digits.

 

Nothing wrong with character classes that help readability, is there?

 

Well, after reading this blogpost from blogs.msdn I hit myself to the head realizing there is. \w in regular expressions equals a-zA-Z in ASCII. A word like ‘façade’ (though in the English dictionary) doesn’t solely consist of \w (or word) characters.

 

Fixing this can easily be done by adopting the use of Unicode character classes in your regular expressions. A list of character classes can be found here.

In Microsoft’s Enterprise Library (successor to the application blocks) it is common to edit an applications configuration in a pretty little tool called the Configuration Console. Offering a similar experience for your applications custom configuration is done by deriving from the EntLib’s base classes and is a time consuming job to do.

 

I am writing a generic configuration node that can be used to manage any type of configuration expressed in XML. Instead of writing custom code for every property that could be edited at configuration time, you fire up the EntLibXmlEditor node and just ‘have a go with it’. Having a go with it either means managing the configuration file's definition (on a development box) or editing the configuration values itself. a description of how my solution works can be found here.

 

While stabilizing the project & working it up to its first beta release I came across this post on Scott Densmore’s weblog. It describes a project called ELCCMG (Enterprise Library Configration Console Module Generator). This project does a similar thing: Generating the ConfigurationNodes Enterprise Library uses in order to reduce the time spent on writing trivial code. The status for this project is set on ‘planning’ though compiling the sources already gives you a good idea of how it works.

 

Though the goal is the same, from what I’ve seen the approach differs.

 

1.)   ELCCMG uses static code generation to create the configuration nodes used by the Condiguration Console. I’m not a big fan of static code generation and decided to make the EntLibXmlEditor do all of its in configuration time dynamically.

 

Obviously a matter of taste, though in my opinion it is quite a hassle to regenerate configuration classes every time your applications configuration changes, during development.

 

2.)   EntLibXmlEditor generates the configuration nodes based on an Xml document. ELCCMG accepts a .net class and expresses its properties in xml when persisting to disk.

 

Again a matter of taste, though I have to admit that generating nodes around the actual classes you plan to use seems easier. The downside might be that your xml definition evolves into something less easy to edit by hand.

 

3.)   ELCCMG uses a standalone windows application to edit & configure the behavior of configuration nodes. The EntLibXmlEditor uses the Configuration Console itself to manage the behavior of the configuration nodes.

 

I think using the Configuration Console’s existing interface is easier to use. ELCCMG could gain flexibility using its UI.

 

For the EntLibXmlEditor using the Console itself means that it has to be compiled against your set of EntLib dll's, I'm not sure whether ELCCMG will have such a requirement.

 

I won’t tell you which tool I think is better as both tools are still being developed.

But I'm pretty sure I'll be watching the ELCCMG’s project process & hopefully get some though rolling on how to improve my own EntLibXmlEditor :-P.

 

Hopefully I manage to wrap up a beta version soon, feels like I’m almost there!!

The GDN Workspace hosting EntLibXmlEditor can be found here.

The GDN Workspace hosting ELCCMG can be found here.

[Follow-up on ‘IOC1: It’s about reuse of functionality’]

 

Whenever someone shouts out “SOA” (or Service Oriented Architecture), most people associate it with stuff like webservices, transports (such as http or .net remoting), protocols (such as soap) and interoperability problems between different technologies (J2EE/.NET).

 

In essence I think SOA isn’t about webservices, though webservices enable the development of SOA. SOA is a way of structuring your application into services; webservices is a way of defining services. In general SOA frameworks are written with enterprise application development scenarios in mind and therefore commonly target webservices (and similar technologies, often next to inproc transports).

 

I think SOA and benefiting from it can perfectly be done without the complex stuff it is commonly associated with. I would like to present IoC-Containers as a facility to build Service Oriented Architectures within your everyday applications. IoC isn’t about transports, protocols, descriptive languages or interoperability. It’s about services!

 

Looking at the code sample from my previous post on IoC, typical usage of an IoC-Container.

 

public class DefaultLoginFunctionality: ILoginFunctionality

 

private ITinyTextFunctionality _resourceManager;

private ILogWriterFunctionality _errorLogger;

 

public DefaultLoginFunctionality()

{

       _resourceManager = (ITinyTextFunctionality) Container.ServeInstance("TinyTextReader");

       _errorLogger = (ILogWriterFunctionality) Container.ServeInstance("LogWriter");

}

 

 

public void DoLogin(string username, string password)

{

       //

       // login code

       //

 

       if (loginUnsuccessfull && _resourceManager != null && _errorLogger != null)

       {

              string logMessage = _resourceManager.GetString("LOGON_UNSUCCESSFUL_MSG");

              _errorLogger.WriteLogEntry(string.Format(logMessage, username));

       }

}



From the code above you might be able to recognize ‘services’ in the XxxFunctionality references.

For example:
The _errorLogger functionality is only known by its interface, a Type object that functions as the contract between consumer and service. The service does not share its implementation with the consumer.

 

Following another SOA guideline, the _errorLogger implementation should never share its private configuration/data/details with other implementations. Every functionalities implementation should be autonomous.



To give our code sample a bit more off a SOA feel, I refactored the code into the following:

 

public class DefaultLoginService: ILoginService

{

       private ITinyTextService _resourceManager;

       private ILogWriterService _errorLogger;

       /** other services this service consumes **/

 

       public DefaultLoginFunctionality()

       {

              _resourceManager = (ITinyTextService) Container.GetService(typeof(ITinyTextService));

              _errorLogger = (ILogWriterService) Container. GetService (typeof(ILogWriterService));

       }

 

 

       public void DoLogin(string username, string password)

       {

              //

              // login code

              //

 

              if (loginUnsuccessfull && _resourceManager != null && _errorLogger != null)

              {

                     string logMessage = _resourceManager.GetString("LOGON_UNSUCCESSFUL_MSG");

                     _errorLogger.WriteLogEntry(string.Format(logMessage, username));

              }

       }

}

 

Please note:

1.) The type names changed from XxxFunctionality into XxxService.

2.) The container exposes the method .GetService, instead of .ServeImplementation

3.) The parameter for the .GetService call on the Container now uses the contract (an interface type) to query a service.

 

Below is the ITinyTextService implementation (from the _resourceManager reference) I use.

 

public class MyTinyTextServiceImplementation: ITinyTextService

{

       private ILogWriterService _errorLogger;

       private IPrivateConfigurationService _privateConfiguration;

 

       public MyTinyTextServiceImplementation()

       {

              _errorLogger = (ILogWriterService) Container.ServeInstance(typeof(ILogWriterService));

              _privateConfiguration = (IPrivateConfigurationService) Container.ServeInstance(typeof(IPrivateConfigurationService));

       }

 

       /** ITinyTextService implementation **/

}

 

Please note:

1.) The ITinyTextService uses an ILogWriterService, for its ‘log writing’ needs.

2.) In order to work autonomously the ITinyTextService uses a service called IPrivateConfiguration which allows a service to have its own configuration. The IPrivateConfiguration can be used to configure the ITinyTextService’s implementation. For example, specify its default culture.

 

 

Other aspects of SOAs:

 

1.) The ability to interoperate, transport over http, or ‘doing the webservices thing’.

IoC-Containers don’t facilitate here. If you would like to ‘do the webservices thing’ from within service out of an IoC-Container, you should use the service as a façade to your werservice. If the ILogWriterService wishes to log its messages over soap to another server somewhere over the internet, the ILogWriterService should do so internally.

Whenever you have more implementations of the ILogWriterService that all share the same contract (=implement the same interface), these can be replaced by one another without programming effort. In your development environment you might log to your system’s EventLog, even though in your production environment a webservice might be used.

 


2.) Versioning of contracts and services.

Versioning services in a Container is less complex than versioning webservices that aim for interopability. Once we decided on using .net types as contract we might as well use the versioning that comes with types in .net. Strongly typing the assemblies that contain the interface declarations does the trick. Once an interface definition is strongly typed and used by services, it should never change.

 

Adding new features to fix shortcomings in your existing interfaces should be done by defining new interfaces. Thanks to the 'multiple inheritance' of interfaces you are able to write services that comply with multiple contracts, you could fix shortcomings in your contract in a new service that complies with the old contract.

 

Interfaces should also be stored in assemblies separate from the interface’s implementations. This should be done to avoid dependencies to the technology used in the interface’s implementations.

I’m pretty sure I heard about partial serialization in a talk about ASMX & the XmlSerializer on DevDays this year. After digging through my CTP 2 release of VS 2K5 I wasn’t able to find a trace of this partial serializing thing by the XmlSerializer class.... :-/.

 

Back to the 'good old' method of writing XmlSerializer support on types the XmlSerializer doesn’t handle. For my particular needs this resulted in the following code fragments:

 

1.) Serializing a Dictionary<K, V> with the XmlSerializer (example only uses Dictionary<string, ContainerDefinition>:

[XmlIgnore()]

 

public Dictionary<string, ContainerDefinition> ContainerDefinitions

 

{

 

      get { return _containerDefinitions; }

 

      set { _containerDefinitions = value; }

 

}

 

 

#region XmlSerializer support

 

 

[XmlArray("ContainerDefinitions")]

 

[XmlArrayItem("Item")]

 

public KeyValuePair<string, ContainerDefinition>[] ContainerDefintionItems

 

{

 

      get

 

      {

 

            List<KeyValuePair<string, ContainerDefinition>> containerDefinitionItemList

 

                  = new List<KeyValuePair<string, ContainerDefinition>>(ContainerDefinitions);

 

 

            return containerDefinitionItemList.ToArray();

 

      }

 

      set

 

      {

 

            List<KeyValuePair<string, ContainerDefinition>> containerDefinitionItemList

 

                  = new List<KeyValuePair<string, ContainerDefinition>>(value);

 

 

            ContainerDefinitions = new Dictionary<string, ContainerDefinition>(containerDefinitionItemList.Count);

 

            foreach (KeyValuePair<string, ContainerDefinition> item in containerDefinitionItemList)

 

            {

 

                  ContainerDefinitions.Add(item.Key, item.Value);

 

            }

 

      }

 

}

 

 

#endregion

 


2.) Serializing a Type with the XmlSerializer

[XmlIgnore]

 

public Type ServiceActivatorType

 

{

 

      get { return _serviceActivatorType; }

 

      set { _serviceActivatorType = value; }

 

}

 

 

#region XmlSerializer support

 

 

[XmlElement("ServiceActivatorType")]

 

public string ServiceActivatorTypeName

 

{

 

      get { return (ServiceActivatorType != null) ? ServiceActivatorType.AssemblyQualifiedName : null; }

 

      set { ServiceActivatorType = Type.GetType(value, false); }

 

}

 

 

#endregion

 



One useful thing I did find in VS.NET 2K5 are ‘template expansions’ (or ‘snippets’). These snippets make writing the code above as right clicking the IDE and filling in the blanks.

 

I zipped the snippets I created out of both XmlSerializer support methods, you can find them here. The snippets in the file should be registered in the IDE’s ‘Code Snippet Manager’ under the ‘Tools’ menu.