Thursday, May 22, 2008

SOA Canonical Cross-Domain Data Semantics

I have over the last year promoted the need for having a business process information model (BPIM) for semantic mediation and business process integration to enable SOA, not to forget enabling consumers such as mashups to do composition and consumption of the provided services, to deliver value to our users.

There has been some discussions about the need for an enterprise to have federated canonical domain models, but I think more and more people tends to believe that BPIM is an important SOA and BPM enabler. This blog post by Joe McKendrick quotes Hub Vandervoort, CTO of Progress Software, on some common SOA challenges:

He recommended three approaches to the problem, including "getting your transports aligned between business entities so that you can use eventing-oriented mechanisms to communicate across domains"; establishing SLA and security policies that ensure visibility; and establishing a common enterprise data model.

"You have to get your semantics aligned among the members," he said. "And that doesn't have to be a common vocabulary in its entirety, but certainly what we regard as the data in flight, those things that fly between domains and different working groups have to be highly normative."

The important part of Vandervoort's message is that you should not try to make a complete Enterprise Data Model, but rather focus on a common information model (CIM) for the "data in flight", i.e. the events, messages and documents of your business processes, when creating your information model.

Thursday, May 15, 2008

Configure MSE UDDI Integration

The Managed Services Engine repository can be synchronized with UDDI. All service endpoints hosted on an MSE runtime server can be exported to make your virtualized services discoverable from e.g. VisualStudio. View this web-cast (slide deck) by Raul Camacho to learn about SOA lifecycle management and MSE service virtualization.

Enable and configure the UDDI sync using the <serviceCatalogUddi> element in the config file of the MSE catalog service executable on the MSE server (Microsoft.MSE.Catalog.ServiceHost.exe.config).

NOTE: In UDDI Services, data published for a service, provider, or tModel can be modified only by the current owner. Make sure that the identity used to publish MSE data to UDDI is the owner of the configured UDDI provider (BusinessKey).

The UDDI sync configuration must adhere to these rules:

  • Make sure that you use the "uddipublic" URLs for "UDDI" authN
  • Make sure that you use the "uddi" URLs for "WINDOWS" authN
  • The identity used to run the MSE catalog service must have access to the UDDI web-services
  • The identity specified for the sync must have publish rights in UDDI and own the BusinessKey
The UDDI Services Console MMC snap-in must be used to configure domain groups for the different UDDI roles, including "publisher" rights.

Using "WINDOWS" authN is strongly recommended. You can specify "UDDI" as the <UddiAuthenticationScheme> and put a username + password of an identity that has access to UDDI in the config file to test the UDDI sync. Do not do this for production systems.

<!-- DO NOT CHANGE THE ORDER OF THE ELEMENTS -->
<serviceCatalogUddi>

<UddiIntegrationMode>true</UddiIntegrationMode>
<UddiPublishUrl>http://***/uddipublic/publish.asmx</UddiPublishUrl>
<UddiInquireUrl>http://***/uddipublic/inquire.asmx</UddiInquireUrl> <BusinessKey> UDDI PROVIDER GUID HERE </BusinessKey>
<UddiAuthenticationScheme>UDDI</UddiAuthenticationScheme>
<UddiUserName>***\***</UddiUserName>
<UddiPassword>*******</UddiPassword>
</serviceCatalogUddi>


Check the UDDI config if you have problems when publishing services and also check the Application Event Log. Use the MMC UDDI Services Console to adjust the logging level to diagnose errors. Note that you must set the level to info / verbose to see SQL exceptions, e.g. when you get an error like this:

Failed to Publish EndPoint service to UDDI due to error [Exception Information Type[FaultException] Message[A UDDI specific error occurred while publishing Endpoint data to UDDI] ].

Using "WINDOWS" against "uddipublic" will give you this error in the event log: UDDI_ERROR_AUTHTOKENREQUIRED_NOTOKENPUBLISHATTEMPT

Note that the UDDI web-portal requires ASP.NET 1.x. Check that the IIS web-sites use ASP.NET 1.x if the UDDI web-pages have errors (e.g. the treeview fails).

Wednesday, May 07, 2008

Design Rules for Model-View-Presenter

In my current project the MVP pattern is used in the supervising controller mode. The MVP pattern is an adaption of the old MVC pattern that incorporates that the capabilities of WinForms views have become smart enough to lift some of the burdens previously implemented in the controller. This applies to e.g. handling click events and data-binding; a presenter only injects the model into the view which exploits data-binding, while a controller explicitly sets the values of each control in the view. In short, a presenter should handle the use-case logic only, not the view logic.

Each view must implement an interface that defines all interactions that the presenter has with the view. This ensures a clear separation between the presenter and the view, and has the advantage of making the presenter easy to unit-test using mocking. The view never calls other modules and services directly; it must always use an event to request that the presenter provides the needed data or service.

This project uses CAB/SCSF to generate the view modules. The generated code is not quite as I would like it, I prefer that the view has no knowledge of the presenter and no direct access to it either as this gives a cleaner separation between views and presenters. I prefer that the view interface defines a set of events that is used to communicate view events to the presenter. This makes it harder for unknowledgable programmers and code monkeys to misuse the presenter reference; making shortcuts and ignoring the reasons for using patterns is very common and leads to unmaintainable code. Read Jeremy Miller's View to Presenter Communication for further opinions on this topic.

The following MVP design rules have a CAB flair, but are generally applicable to any MVP implementation:

1. All views should have a XxxView suffix: TaskView/ITaskView
2. All presenters should have a XxxPresenter suffix: TaskViewPresenter
3. Let the presenter do all use-case processing, but keep GUI control details in the view
4. All presenter methods called by the view must start with OnXxx() as they are events by design (MVP)
5. Calls from the view to the presenter should be kept at an absolute minimum, and used for "event" type calls only: _presenter.OnViewReady();
6. It is FORBIDDEN to use the presenter reference to access the model or services directly, no return values from presenter methods
7. Calls from the presenter to the view MUST go via the interface only
8. No methods in the view shall be public unless they are defined in the interface
9. It is FORBIDDEN to access the view from anywhere but the presenter, except for loading and showing the view from the CAB ModuleController
10. The interface methods shall have long meaningful names (not "SetDataSource") based on the domain language of the use-case
11. The interface should contain methods only, no properties - afterall the presenter drives the use-case by calling methods, not by setting data
12. All data in the MVP component should be kept in the model, no data should exist only as properties of UI controls
13. The methods of the view interface should not contain UI control name references (e.g. AddExplorerBarGroup) as this makes the presenter know too much about the implementation technology of the view
14. Stick with domain naming in the view methods (e.g. AddTaskGroupHeader), this makes the code easier to understand and the tests self-describing

Rule 11 and 12 might surprise you if your perception of the model is that it contains business entities only - traditional database-driven design thinking. The model is rather business process documents that are involved in the use-case, i.e. domain entity and value objects. Even views used for searching have a model, it is a specification or query object. Jeremy has some guidelines on assigning responsibilities in MVP.

Rule 6 helps adhering to the "tell, don't ask" principle - properties make it far too easy to ask, rather use methods on the view to tell it what to do. I've seen design-time view data-binding directly against presenter properties, not exactly separation of concerns. Neither is it very testable, as there is no interaction from the presenter through the view's interface when the view asks the presenter directly. When mocking the view, there will be no recorded / testable interaction.

Using long meaningful names in the view interface has the nice side-effect of making the presenter unit-tests a kind of mini documentation.

I wish there was a FxCop Contrib project on CodePlex like for EntLib, CAB/SCSF and ASP.NET MVC. Then maybe I would write and publish some of these MVP design rules as custom FxCop rules.

Sunday, May 04, 2008

On Tokens, Claims, Tickets, SAML

There always seems to be a lot of confusion about tokens, tickets, and claims; which in combination with the very broad term security (authN, authZ, confidentiality, integrity, auditing, devices, data, etc) make every discussion about "security" a bit obscure.

A simple explanation of tokens and claims: a Security Token is a signed and encrypted set of Claims. A claim is just some right on a specific resource of a given resource type that the token holder claims to have. To accept this claim, you need to trust the token issuer. The typical example of a claim is the user's identity (the claim), which e.g. can be the domain login name (the resource) asserted by Windows (the issuer).

The terms Security Token and Claim are used in the WS-Trust standard. Kerberos use the term ticket instead of token, i.e. the ticket proves the identity of the user. A SAML token is another type of security token.

Watch the Channel9 video where Vittorio Bertocci explains WS-Trust and the token encryption and signing mechanism in depth, using a claim set based on a driver license resource. Note that only video download seems to work.

In addition, read the post series by Sam Gentile about SAML, which expands into claims-based security and WS-Trust / WS-Federation.

Friday, May 02, 2008

SCSF Dependency Injection Container, CAB WorkItem

Getting started with CAB/SCSF can be a bit daunting, and this article is a summary of the most important aspects regarding the mysterious CAB workitem. I've found this to be a good intro to CAB, start with part 18: http://richnewman.wordpress.com/intro-to-cab-toc/

The CAB workitem is simply a dependency injection container, even if "wrongly" promoted as an implementation of a use case. A use case contains no UI-details or service implementation references, but of course these artifacts are needed to realize a use case in an application. The workitem is a container of resources needed to implement a use case.

A DI-container is a collection of resources than can be located using a resource locator that is used to resolve resource injection requests at run-time. The resources can be loaded into the container either dynamically or through XML config. The workitem DI-container has several collections of resources, which can be quite confusing. A workitem has these collections:


  • Items: all objects added to any of the child collections including this, except Workspace.SmartParts; independent of type of resource.
  • WorkItems: child WorkItem objects, must inherit CAB.WorkItem.
  • Services: any object added as a service. NOTE: the container can only contain one instance of each service type.
  • Workspaces: encapsulate a particular visual layout of controls and SmartParts, such as within tabbed pages.
  • SmartParts: any object marked with [SmartPart] in the class definition, do not have to be a visual component.
  • Workspace.SmartParts: visual components shown in the workspace, must inherit System.Windows.Forms.Control. NOTE: these items are not added to the .Items or .SmartParts collections on the workitem.
In addition, the workitem DI-containers can be nested, i.e. a workitem can contain other workitems.

When the DI-container tries to resolve a [ServiceDependency] injection or just Get<IService> for a service, it looks in the nested set of containers from the current workitem and up through the parent workitems, including the root workitem to find the service. The service locator does not look through the set of child workitems. Thus, shared services should be placed towards the root or in the root workitem for the service locator to find them.


One aspect of the workitem Services collection that most CAB developers seems to have missed, is that even if you can add only one instance of a service to a workitem, you still can add separate instances of the same service to child workitems. The service locator will find the nearest service in the tree towards the root. E.g. the ActionCatalog service can be added to several ModuleController first-level workitems, in addition to the root workitem. We have used this feature to add several scope-based services such as a SharedModelCacheSevice and a RibbonControllerService at different levels of the workitem structure. This way, the same service can have different scopes in a CAB solution, dependent on where it is injected. The scope controls how workitem resources are located by the resource locator, e.g. where the locator looks for Services, Commands and UIExtensionSites.

Note that the resource locator strategy only applies to these workitem collections: Services, Workspaces, Commands, EventTopics, UIExtensionSites.

When the SmartClient application starts, it will create the root workitem and add a set of CAB services to it:

public ... class SmartClientApplication<TWorkItem, TShell> ...
{
protected override void AddServices()
{
RootWorkItem.Services.AddNew <ProfileCatalogModuleInfoStore, IModuleInfoStore>();
RootWorkItem.Services.AddNew <WorkspaceLocatorService, IWorkspaceLocatorService>();
RootWorkItem.Services.AddNew <XmlStreamDependentModuleEnumerator, IModuleEnumerator>();
RootWorkItem.Services.AddNew <DependentModuleLoaderService, IModuleLoaderService>();
RootWorkItem.Services.AddOnDemand <ActionCatalogService, IActionCatalogService>();
RootWorkItem.Services.AddOnDemand <EntityTranslatorService, IEntityTranslatorService>();
}
}

These standard CAB services are available from all over CAB as they are added to the root workitem that becomes the ultimate parent of all other workitems loaded into the SmartClient application.

In addition to the standard set of CAB services, the custom CAB modules that get loaded will typically add extra CAB services into the root workitem. SCSF will load CAB modules as defined in ProfileCatalog.XML and this will trigger the CAB module initialization mechanism filling the workitem collections and followed by the DI-container resolving.

What adds to the somewhat complicated workitem collections mechanism is that several of these CAB services themselves are collections of other shared objects. E.g. the EntityTranslatorService is a collection of translators that can be added to and located within that service. Note that the DI-container only performs the resource resolving and dependency injection on objects that are added directly to a workitem collection. Thus, objects not added directly to a workitem collection will not get any DI magic performed on them. E.g. if you create a service agent from within a CAB service to call a web-service, that agent will not be subject to any DI resolving. This can be very confusing when [ServiceDependency] objects are not injected as planned, thus be very careful when designing your solution.

NOTE: do not try to access resources that must be resolved by the DI-container, from within class constructors, as the resource may not have been injected yet. Use the [InjectionConstructor] attribute on your constructor if you need to force the resource locator to resolve and inject services that you need.

Using the DI-Container from CAB Modules

CAB Services are usually implemented using CAB foundation modules, but can also be implemented using CAB business modules. The former module type is applicable for shared CAB services and components, such as modules that provide access to web-services; while the latter module type is suitable for use-case specific CAB components. Note that both types of resources are "services" in CAB as they are added to the workitem Services collection. This overloading of the term "service" should not make you confuse CAB service modules with WCF service gateways, even if the CAB service used the WCF service.

Adding CAB services from CAB modules

A foundation module is a bare-bones module (the original CAB module) as it is just for implementing a container for shared components.

A business module is a module (new in SCSF, extending the original CAB module) enhanced with the application controller pattern as it for implementing a container for use-case specific components. The SCSF module adds the
ControlledWorkItem to separate the use-case related code from the workitem container related code (in CAB you had to put the use-case controller code in the workitem class, mixing the DI-container logic with the use-case logic).

So even if you could implement an AddServices method in the ModuleController and call it from its Run method, I would recommended that you still add module services from Module.AddServices method. This keeps the container related code separated from the use-case related code:

public override void AddServices()
{
//NOTE: must add UserAccessClaimSet first, as NavigationService depends on this service
WorkItem.RootWorkItem.Services.AddNew <UserAccessClaimSet, IUserAccessClaimSet>();
WorkItem.RootWorkItem.Services.AddNew <NavigationService, INavigationService>();
}

Prefer adding services like this over the other mechanisms provided by SCSF (
app.config / [Service] attribute).

Resolving and using CAB services


To be able to use the CAB services they must be gotten from the workitem DI-container. There are two ways of doing this, using the service collection Get<IService> method or using dependency injection with the [ServiceDependency] attribute. The DI way is preferred as the class using the service can then get the service reference once and use it multiple places. The Get<IService> way has the advantage that it can be called with a bool EnsureExists parameter that will throw an exception if the service is not (yet) registered in the workitem DI-container.

Use the [ServiceDependency] attribute either to inject a service into a class property or in the class c'tor:


[ServiceDependency]
public IUserAccessClaimSet Service
{set { _service = value; }}

[InjectionConstructor]
public NavigationService([ServiceDependency] IUserAccessClaimSet userAccessClaimSet)
{
_userAccessClaimSet = userAccessClaimSet;
}

Getting the service directly is more explicit and allows for using the EnsureExists parameter:

IUserAccessClaimSet costOfGasService = WorkItem.Services.Get<IUserAccessClaimSet>(true);

Without the EnsureExists parameter, the returned service can be null and your code will then not throw an exception when getting the service, but rather on the first service invokation later on, which can make it harder to diagnose the actual cause of the failure. Using the [ServiceDependency] attribute has the same weakness, and this is a common cause of CAB perplexity.
Still, I would recommend using the [ServiceDependency] attribute.



Using the DI-container from CAB views

All CAB views exist within a CAB business module and must thus use one of the recommended methods for resolving service dependencies, preferring the [ServiceDependency] attribute. CAB views are designed using the 'supervising controller' MVP pattern, and the presenter object is added to the workitem Items collection like this:

_presenter = _workitem.Items.AddNew<TaskViewPresenter>();

Adding it to the Items collection of the workitem DI-container triggers the dependency injection resolver.