Reflections on SOA(2 min read)

One way I expand my professional knowledge is by reading "good" books on software engineering; those books that are either commonly referenced classics or highly recommended (see sidebar for short reviews of some recommended books).

I have recently been reading "Pattern-Oriented Software Architecture, volume 1", by Buschmann, et al. (commonly referred to as POSA), which includes one of the early (1996) formalisations of the Layers pattern.

What does this have to do with SOA?

Well, the topic came up in a recent training course of what is SOA / what is a service. The training course level was such that only a basic description was appropriate, but what immediately jumped to my mind as important is that a Service Oriented Architecture usually consists of both coarse-grained business services, as well as fine-grained implementation services (often with a workflow component as a means to aggregate them).

Although a lot of knowledge can be learnt on the job, being passed on by other software engineers, it can sometimes be an eye-opener to actually go back and read the original description.

In this case, when defining an Service Oriented Architecture I would strongly suggest reviewing the Layers pattern and think about how your services might be structured in layers. Think about the different abstraction levels you have in your system, name the different layers and assign tasks to each of them. In particular, think about some of the issues from step 4 ("Specify the services"), and step 5:

"5. Refine the layering. Iterate over steps 1 to 4. It is usually not possible to define an abstraction criterion precisely before thinking about the implied layers and their services. Alternately, it is usually wrong to define components and services first and later impose a layered structure on them..."

One way I have seen service oriented architectures broken up is with different layers for Business Process Services, Business Function Services and Data Services, each with their own responsibility and features.

For example Data Services encapsulate business data entities specific to a slice of the business and are usually atomic, stateless, don't change often and are highly reusable, whereas Business Process Services are designed to encapsulate business process and workflow, are implemented through a stateful orchestration and will change more often.

There is a good diagram of how the different abstraction levels (Layers) of services can interact in "Understanding Service Oriented Architecture" in the inaugural January 2004 issue of the Microsoft Architecture Journal.

Work around for deployment of MOSS site with variations(4 min read)

One way to deploy MOSS (or SharePoint) sites is via stsadm export/import. There are, however, a few known problems, for example items hidden in navigation reappear and the first time you deploy your custom master pages are not applied. Fixes are possible; manually re-hide the items, and deploying a second (or more) time resolves the master page issue.

(Aside: I suspect the master page issue is a dependency problem -- during the deployment it tries to set the master page before it has been deployed, i.e. before it exists, and fails. The dependency is then resolved if you deploy again, as this time the master page does exist.)

However -- running the deployment (stsadm -o import) twice causes issues if you have variations (multilingual) enabled for your site. We found this out the hard way trying to deploy a large multilingual site into our test environment. When you try to access the site after the second deployment, you get the following nasty error (you need to turn off friendly errors and enable debugging, etc to troubleshoot):

Source Error:
Line 47:         private string GetRedirectTargetUrl()
Line 48:         {
Line 49:             ReadOnlyCollection<VariationLabel> spawnedLabels = Variations.Current.UserAccessibleLabels;
Line 50:             if (spawnedLabels.Count > 0)
Line 51:             {

Source File: c:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES\VariationsRootLanding.ascx    Line: 49

Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
   Microsoft.SharePoint.Publishing.Variations.InitializeUserAccessibleLabels() +199
   Microsoft.SharePoint.Publishing.Variations.get_UserAccessibleLabels() +33
   ASP._controltemplates_variationsrootlanding_ascx.GetRedirectTargetUrl() +44
   ASP._controltemplates_variationsrootlanding_ascx.OnLoad(EventArgs e) +18
   System.Web.UI.Control.LoadRecursive() +47
   System.Web.UI.Control.LoadRecursive() +131
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061

Even worse, some of the administration pages also break, for example trying to access /_Layouts/sitemanager.aspx results in the following error:

Object reference not set to an instance of an object.   at Microsoft.SharePoint.Publishing.Internal.VariationsPublishingOperationValidator.EstablishLabels()
   at Microsoft.SharePoint.Publishing.Internal.VariationsPublishingOperationValidator.Examine()
   at Microsoft.SharePoint.Publishing.Internal.WebControls.SmtWebEcbMenu.<>c__DisplayClass5.<setupTypeSpecificMenu>b__0()

The site itself should work if you manually go direct to one of the individual language sites, e.g. /en (or whatever your variations are). You can also still access /_layouts/settings.aspx, and if you look at the variation labels setup you will see that all of the variations are appearing twice!

If you deploy a third time, say a new build from the development team, then you will find that all the variation labels are now appearing three times!

The problem has been communicated to Microsoft, and they are working on a hotfix, but in the meanwhile poking around in the SharePoint content database we came up with the following SQL workaround.

Note: This is not complete; you will need to execute each statement and update the GUIDs into the next. It's safer to check it as you go rather than just start deleting parts of your database.

-- Select the target content database
use xxxxxxxx
go

-- Get Id of top level web
select top 100 Id, *
from Webs
where ParentWebId is null

-- Get tp_ID of the 'Variation Labels' list for that web
select top 100 tp_ID, *
from AllLists
where tp_WebId = '[Id of top level web]'
and tp_Title = 'Variation Labels'

-- Check the data items in that list.
select top 100 *
from AllUserData
where tp_ListId = '[tp_ID of variation labels list]'

-- Remove the duplicate labels (created after first import)
select * -- delete
from AllUserData
where tp_ListId = '[tp_ID of variation labels list]'
and tp_Created > '[some date/time after first deployment]'

After you figure out the GUIDs, just run the delete after every time you do a deployment (presuming you haven't added any new items).

Addendum:

A while later we discovered also that there were similar problems with duplicate cache profiles and content reports. The extra items can be deleted, but the report filters still don't seem to work. The investigations are continuing, but at least we can deploy now.

To see the other duplications after import, use the following SQL:

-- The same applies to caching and reporting setup
select *
from AllUserData
where tp_ListId in
(
  select tp_ID
  from AllLists
  where tp_WebId = '[Id of top level web]'
  and (tp_Title = 'Cache Profiles'
       or tp_Title = 'Content and Structure Reports')
)


Dependency injection via System.ComponentModel(1 min read)

In reference to a recent post on Matthew's blog (http://mcosier.blogspot.com/2005/07/inversion-of-control-ioc-or-dependency.html).

(Graeme [Strange] suggested I catch up with the Readify blogs, so I've been reading recent posts.)

Note that the .NET Framework already includes a complete implementation of a dependency injection framework in the System.ComponentModel namespace.

It allows you to inject components which implement an interface into a service locator at runtime. Service consumers are then coded to search for the components they want via the public interface. All the plumbing handling service registration, etc, is handled in the .NET Framework.

The following post by Daniel Cazzulino has more information and gives some examples.

http://weblogs.asp.net/cazzu/archive/2004/05/10/129140.aspx#129156

Mitch Denny has also previously posted on this.

http://notgartner.com/posts/906.aspx