It's 2008. Where's my flying car? RSS 2.0
 Tuesday, July 01, 2003

German Software Legends

A picture named teched2003-aufsteller.jpg

The parodies on the "Software Legends" cardboard cutouts that were all over TechEd Dallas even continues over here in Barcelona. Ralf Westphal had the idea for a quick photo session a few hours ago and actually created a set of cutouts of himself, Christian Weyer, myself and the legend of legends, Juval Löwy (here is the legendary "Cardboard Juval Conquers Dallas" photo series by Stephen Forte).

Tuesday, July 01, 2003 7:40:46 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

ASP.NET Soap Extension Wizard

While preparing for my WEB404 talk on Web Services extensibility tomorrow at 18:15 in Room 7 at TechEd Barcelona, I remembered that I had built this some 9 months ago. So I made a version that works for Visual Studio .NET 2003 and will show that tomorrow. Here's the current zip file, which includes the installation notes. The zip file contains a file 'InstallerUtil.cs' that implements a helper class supporting the installer that the wizard generates. Put it into a utility assembly and reference it. Aside from that, it's just 3 simple steps to get it running.

Tuesday, July 01, 2003 7:16:40 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

 Monday, June 30, 2003

(Some background reading for my DEV359 session in Barcelona on Friday July 7, 16:00, Room 7)

 

Summary of a Year with Aspects

 

A bit less than a year ago, I got a few little hints.

 

Early last year I had been playing around with the managed portion of the .NET Framework’s ServicedComponent infrastructure and wanted to smuggle code between the client and server side for purposes of validating parameters, monitoring and other things. I learned a lot about the interaction between Remoting and the Enterprise Services infrastructure, but found that there was no way to get interception working using managed code. So I talked to some friends at Microsoft about this and after quite a bit of begging they pointed me to the relevant public patents on the COM+ extensibility points, which are documented there – in legal speak – and nowhere else. I also got a hint or two on what GUIDs to look up in the registry and a few other tips, which all wasn’t much but enough to get things rolling. Armed with plenty of assembly-level debugging experience from the time when I wrote large COM frameworks in unmanaged code, I went digging. Deep.

 

Now, a year later, I have two activators and one policy almost working (more on that in a bit) and what I have done is – by all the Enterprise Services people at Microsoft tell me – possibly the only inside-COM+ extension ever built by anyone outside of Microsoft. And because most of the people in that respective product group are busy building the next generation base infrastructure for Enterprise Services, I even seem to be the only one who has been writing new code in that area for at least two years.

 

Still, I am about to give up.

 

The reason for that is technical but not really a problem of Enterprise Services or COM or the .NET Framework. It’s the fact that I am trying to use a beautifully designed extensibility point in the exact way it was envisioned, but for which nobody ever assumed that it’d be used anywhere but outside the product group.

 

Let’s call that a problem of “opaque aspects”. However, before I can explain the problem, I need to explain a little more how the Enterprise Services (COM+) infrastructure works internally. I am simplifying a bit here, but it’s enough to get the picture.

 

Whenever a COM object is created from any programming environment, it happens through CoCreateInstanceEx in the end. One in CoCreateInstanceEx, the component’s configuration including the server identity (DLL, process or remote machine), threading models and all of the other essentials is looked up from configuration. The configuration is actually a chain of providers. The first stage is an in-memory cache, the second stage reads the COM+ catalog (which is a very efficient, COM+ specific ISAM database) and the third stage goes to the registry. If a component of which an instance shall be created is found in the COM+ catalog, it is called “configured” and instances are constructed using the COM+ infrastructure. Object construction happens through a chain of so-called “activators”. An activator is a COM object that gets associated with a component through one (or multiple) entries in the catalog. Each component can have any number of activators in each “stage”. The stages indicate on which level the activation process is currently working: client context, client machine, server machine, server process and server context. In each stage, an activator can perform work that needs to be done before the next stage can be entered. If you want to add a “policy” to a newly created context, you will do so at the “server process” stage, because the context setup needs to be complete before the activation process can enter into the “server context” stage. When you install a policy you are indeed usually adding two things to the context: the first thing is usually called a “property” and is an object that can be accessed (by those who have the right header files) using the object context at the application level, the second thing is an interceptor that can subscribe to get notified whenever a call passes in and out of the activated object’s context. Both, the interceptor and the property can be implemented on the same class and that’s what I usually do.

 

So, in short, the role of the activator is to deal with object creation, the property maintains related state and the policy acts on calls entering and leaving the context. If you configure a class to support just-in-time activation (JITA), the policy will inspect the “done” bit in the property on the call “leave” event and deactivate and disconnect the object if it’s set. When the next call gets in (“enter”) a new object is created and connected. If you configure transactions, a transaction is created by the policy on “enter” and terminated on “leave” if the “done” bit is set or whenever the context is closed. All of COM+ is based on these three elements.

 

I wrote two activators/policies. The first activator redirects activations into a secondary, configurable application domain in order to fix the problem that all managed Enterprise Services components end up being created in the default domain. The problem with the default domain for out-of-process components is that they all live on top of dllhost.exe and therefore the XML configuration file for all Enterprise Services apps is dllhost.exe.config in the Windows system directory. That’s annoying and therefore I decided to fix that.

 

The second activator and the policy exists to enable custom extensibility. The goal is to intercept all calls with all inbound and outbound parameters and pass this information on to custom, managed extensibility points that are attached to the class metadata using attributes. So, in essence, that’s an attribute-driven way to implement aspects. What the “AOP people” use pointcuts for in AspectJ is done here using attributes. It’s just a different way to express the necessary metadata to get the interception (“weaving”) going.

 

So, if you write an attribute (aspect) class called “GreaterThanAttribute” that implements a specific interface and put that on a method parameter like void MyFunc( [GreaterThan(1)] int param ) the aspect is going to be called every time just before the function actually gets invoked on the server. If the validation rule is violated, the aspect can throw an exception and deny the call to proceed. That was the idea and I got it to work – almost.

 

The “almost” is the sad part of the story. The code has been at 98% complete for the past four to five months and that’s where I am stuck.

There are multiple problems and most of them are related to the way Enterprise Services (managed) is cheating on the unmanaged COM+ infrastructure in order to keep managed calls managed calls and avoid COM/Interop. When you make an in-process call from managed code to managed code, there is no COM call. In fact, all that COM+ learns about the call is that it happens. It doesn’t learn about the exact object that the call is happing on, it doesn’t know about any of the parameters, it just doesn’t know. When you make an out-of-process call from managed code to managed code, there is also no proper COM call in most cases. While the call will come in via COM transport, the actual call data is contained within a binary package passed to on of the methods on the IRemoteDispatch COM interface. The managed implementation of that will unmarshal that package, finds a Remoting IMessage object and will dispatch that on the managed server object. These call paths exist in parallel with the support for inproc and outproc calls from unmanaged clients.

 

None of the existing COM+ policies ever looks at parameters, but because I wanted to allow parameter inspection I actually had to get at the parameters. Here’s where it gets hairy. For inproc, managed-to-managed calls, there is no COM call and therefore all the information about the call turns out to be NULL in the calls on the policy. No information. How shall I get at the parameters if all I have is nothing? I remember staring at the call stack in the debugger with little hope to get anywhere (that was several weeks and a couple of thousand lines into the project) and seeing everything being NULL, while all information I wanted to have was twelve stack frames above the current position on the stack.

 

The solution for that problem starts ugly: __asm mov __EBP, ebp. I ended up writing a custom stack walk (and having to compensate for an odd __cdecl frame) that figures out the right frame by a certain signature and steals the necessary parameters from “up there”. That worked. The outproc, managed-to-managed case was fairly easy, because I could simply unmarshal the IMessage myself using the BinaryFormatter. What turned out to be way more complicated than thought was the “traditional” case of unmanaged calls. First, I need to decode IDispatch::Invoke calls and correlate them with the target object “by hand”. That’s hard. Secondly, I need to chain in a universal interceptor that proxies each and every interface on the actual backend object in order to see calls that come in as regular COM calls. In essence this means that the activator will have the default activator create the backend object first, wrap the reference into the interceptor class and return the interceptor. Here’s where it gets ugly.

 

The “tracker” property/policy that gives you all the cute spinning balls and the somewhat useful statistics in the Component Services explorer doesn’t like the interceptor. While what I am doing is perfectly legal COM, the tracker just doesn’t expect that sort of thing to happen and gets confused. Just in time activation and object pooling have similar issues with that interceptor and either are hard to convince to deal with it (JITA) or simply crash (Pooling). The more services and combination of services you look at, the more colorful the effects become. COM+ is a well-tuned, perfectly integrated set of aspect-like services. The issue is that they don’t expect strangers to show up in the house. Once you introduce any significant changes into the behavior of the infrastructure, the problems you need to deal with get totally out of hand.

 

The underlying problem is that with aspects, in general, you get the same problems as with objects vs. components. Chaining an aspect into an activation or call chain is very much like overriding a virtual method of a class whose behavior you don’t fully understand. Because the combination and resulting order of aspects results in unknown preconditions for the activities of your code, you will have to understand the interaction of any configuration’s resulting set of aspects in order to get everything right. And just as with classes where you can override virtual functions that either means you will have to have the full source code to look at, change and recompile or very precise documentation to get things working, at all. The real problem is that the problems never end. You develop your aspects assuming a set of pre-existing other aspects that you need to be friendly to and someone else does the same. You combine the two resulting aspects on a single class and everything breaks, because the other person’s aspect doesn’t know to be friendly to yours.

 

There are very few use-cases where aspects can ever be truly independent of other aspects. “Passive” aspects like logging and monitoring seem harmless and “gatekeepers” like argument validation and custom authorization aspects are such use-cases.

 

However, even those may have important dependencies. If you log call data into a database for statistics, billing ore other purposes, what do you do if the call is transactional and fails? Do you want to roll back the call data, too? If so, you need to be behind the transaction aspect, if not you need to be before it. If you validate arguments and throw an exception before the call is ever executed, does that get logged and how? If you introduce custom authorization that should definitely happen before transactions are created. This list could go on forever.

 

Don’t get me wrong, I still see value in the interception approach for this small set of use-cases if you know what you are doing. You can save a lot of code by declaring the need for services in the Enterprise Services way instead of using them imperatively. However, for multiple development organizations to “cooperate anonymously” the model of putting aspects into a simple processing pipeline that acts on messages as they pass in and out of a context or to and from a method is severely broken and insufficient. In order to make that model work, we need something like COM. No, not the technology itself, but we need something that does for aspects what COM did for objects: Allowing multiple parties to build composable parts that can be queried for their requirements and capabilities and implement well-known protocols for effective coordination. I still think that’s entirely possible to do and – as I have mentioned earlier – I have some ideas for such a framework model, including using 2 phase-commit style processing, but that’s not going to fix the problems one faces in existing environments.

 

I learned a lot doing all this work, so it was definitely not a waste of time. I will move the Enterprise Services aspect framework portions out of the core utility assemblies and into set of special assemblies and declare it as “for experimental use only” for now.  You only ever really learn when you fail ;)

Monday, June 30, 2003 6:14:27 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [2] - Trackback

 Sunday, June 29, 2003

Barcelona!

It's TechEd Europe time. I got into Barcelona yesterday, arriving from Tunis where I spoke at the first North Africa Developer Conference. It was great event at a fantastic location. I mean ... how much better can it get that a beach resort where the session rooms are 500m away from the beach. Malek Kemmou, the Microsoft Regional Director from Morocco and the speaker rock-star in North Africa was the most excellent host one could imagine.

Now I am sitting at the speaker's hotel in the lobby (wireless enabled) checking email and prepping demos. I am looking forward to meet lots of friends from all around Europe, to quite a few parties and I am sure my talks are going to be fun, too. And what's even better: This event marks the end of a stretch of about 4 months (excluding that one week of vacation) that I have been almost constantly on the road. After Barcelona I will actually get some time at the office, start to figure out new stuff and can complete and consolidate a bunch of things that I started during this time but could never get quite done. And that also means that this blog will be much less boring than it was in the last couple of weeks ;)

Sunday, June 29, 2003 4:04:55 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

 Tuesday, June 24, 2003

Conceptual talks vs. coding talks

I am in Frankfurt now, coming from Dubai, going to Tunis. Yesterday I talked about the relevance of contracts and agreement in a Web Services environment and about scalability patterns to use with Enterprise Services at the Microsoft Research "Crash Course" that was organized for professors from all across the Middle East, Eastern Mediterreanean and African regions. This wasn't my first event in the academic space, but certainly the largest so far. And it's a very different audience to address, indeed. In two 55 minute talks I spent less than 5 minutes each highlighting and explaining a couple of product features and the rest of the time was only about underlying concepts and strategy.

I start to think that these types of talks just make more sense to conference attendees than "coding sessions". Everyone can pick up a "how-to" book, read the reference material or poke around in samples at home. For me, an ideal conference inspires, highlight things that are off the beaten path and provides insights into the "why" more than into the "how". Having said that, it's pretty frustrating when you are have given a purely conceptual talk that went really well, you get great feedback from the interested people you talk to afterwards and then you get a comment like "very bad, there was no demo" or simply "more demos" in the written feedback. I should probably start blogging attendee comments and write my comments on comments. I guess I'll do that for TechEd Europe. Beware ;)

Tuesday, June 24, 2003 12:40:15 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

 Saturday, June 21, 2003

Hitting the road again...

I didn't take the notebook and didn't even cheat last week (no Internet Cafes, no hidden PocketPC, etc).

I went to a small sea resort at the Baltic Sea in one of the "new" states in the eastern part of Germany. The average age of the tourists there seemed to be about 65 and hence there was no danger of wild partying, which was indeed a Good Thing. I stayed there for three days and then went to see the sights of some cities "up north" on a lazy two day trip back home (it'd usually take me about 8 hrs of driving). I went to Wismar and Schwerin, places around Lübeck and also did the essential touristy thing in Hamburg by taking a boat tour through the seaport (which is the 2nd largest in Europe). I haven't been too much to our eastern states in recent years and it's great to see how the visible differences between "the East" and "the West" have vanished for the most part and that what's left are just normal regional differences. All in all it was a week that most people would probably call "horribly boring" :)

Today's travel destination is Dubai -- now again with a notebook and using the time on plane to prep for tomorrow's event ;)

Saturday, June 21, 2003 10:29:22 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

 Monday, June 16, 2003

Out of here....

I am taking a week off and will drive up north towards the sea. Computer stays behind. I need a break. Will be back on Saturday and then pack up to go to Dubai and Tunis (for the North Africa Developers Conference) and then to Barcelona for TechEd Europe, which is surely going to be the event highlight of the year. I give five talks in Barcelona, including a chalk talk together with my very newtelligent colleagues:

Chalk Talk: Gotchas from porting DNA to .NET (CHT012)
Speakers: Clemens Vasters, Achim Oellers, Joerg Freiberger 
+ 2 July 2003, 08:30h

Microsoft® .NET Web Services Internals : I Didn't Know You Could Do That!  (WEB404) 
+ 2 July 2003, 18:15h

Loose Coupling an Serialization Patterns : The Holy Grail of Service Design  (WEB400)
+ 3 July 2003, 10:00h

Layers and Tiers (DEV387)
+ 3 July 2003, 18:15h

Aspect-Oriented Programming (DEV359)
+ 4 July 2003, 16:00h

Monday, June 16, 2003 12:20:54 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

 Sunday, June 15, 2003

SDK

It's neither finished nor perfect, but it's a lot of code and I want to get something out before I leave for my short vacation. A current "daily build" of the newtelligence SDK. May or may not work for you, it does for me. Includes, mostly in source code form, all the base classes I used for the TechEd Demos. Please be advised that everything related to newtelligence.EnterpriseServices.AspectServicedComponent currently breaks with object pooling and leaks lotsa memory in any out-of-process case. Those issues doesn't affect any of the other classes.  Readme, MSI (3.6MB)

Sunday, June 15, 2003 6:56:24 AM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

 Saturday, June 14, 2003

It got increasingly difficult to distribute my sample code, because the dependencies on the set of standard libraries that I've built over the past months just keep growing. I fell in the same trap for the "polished" version of the samples for TechEd so that I decided to make a cut and make a whole "SDK" out of this stuff, finally (I think I've written about that a while ago) and simply make it a prerequisite for installing additional demos. That takes away a lot of the repetitive work for building installers over and over again. The MSI file is almost finished and I think I should be able to make a first drop available by tomorrow.

From Monday until the end of the week I will take a desperately needed week of vacation. I'll just get into the car and drive up north to the sea. No computer in the luggage. I won't even try to read email. 

 

Saturday, June 14, 2003 12:41:15 PM (Pacific Daylight Time, UTC-07:00)  #    Comments [0] - Trackback

Stuff
About the author/Disclaimer

The content of this site are my own personal opinions and do not represent my employer's view in anyway. In addition, my thoughts and opinions often change, and as a weblog is intended to provide a semi-permanent point in time snapshot you should not consider out of date posts to reflect my current thoughts and opinions.

© Copyright 2008
Clemens Vasters
Sign In
Statistics
Total Posts: 717
This Year: 11
This Month: 0
This Week: 0
Comments: 1220
Themes
Pick a theme:
All Content © 2008, Clemens Vasters
DasBlog theme 'Business' created by Christoph De Baene (delarou)