.NET: Enterprise Services
Door Michiel van Otegem
8 augustus 2006
Sommige applicaties hebben eisen die net even verder gaan dan wat een normaal
ontwikkelplatform biedt. Dit geldt voor applicaties gebaseerd op COM, maar net zo goed
voor .NET. Binnen .NET maken we voor die applicaties gebruik van Enterprise Services,
beter bekend als COM+ Component Services.
Bij mensen die al enigszins bekend zijn met .NET, moeten er nu allerlei bellen gaan
rinkelen. Want .NET heeft toch helemaal niets te maken met COM? Correct, maar COM+ is
geen COM. COM+ is eigenlijk een verzameling diensten waar COM gebruik van kan maken.
Die diensten zijn zo generiek, dat ze eigenlijk voor elke component technologie wat
te bieden hebben, dus ook voor .NET. Waar de naamsverwarring vandaan komt kun je lezen
in het kader "De geschiedenis van COM+ Component Services".
De diensten die COM+ Components Services (verder in dit artikel genoemd COM+) biedt zijn
allemaal bedoeld om het leven van ontwikkelaars en beheerders makkelijker te maken. Een
van de meest in het oog springende diensten is transactie management. Je kunt een component
zo maken dat het deel kan nemen in een COM+ transactie. Binnen een transactie wordt gezorgd
dat alle operaties die door verschillende componenten uitgevoerd worden allemaal goed gaan,
of allemaal niet uitgevoerd worden. Door gebruik te maken van COM+, is hiervoor nauwelijks
extra code nodig, omdat COM+ het op zich neemt alle componenten te melden of de transactie
gelukt is of niet. Maakt je component gebruik van bijvoorbeeld SQL Server, dan worden alle
gegevens die je gewijzigd hebt toen de transactie nog liep automatisch teruggedraaid. Doet
je component iets heel specifieks, dan kan het nodig zijn een functie te bieden die de zaken
terugdraait als de transactie faalt, maar verder hoef je je niet druk te maken om alle zaken
die met transacties te maken hebben. Doordat zowel COM componenten als .NET componenten gebruik
kunnen maken van COM+, is het mogelijk om beide soorten componenten te gebruiken binnen dezelfde
transactie. Zo maakt COM+ het dus ook relatief eenvoudig om hybride applicaties te maken.
Een dienst die verwant is aan transactie management is synchronisatie. Veel COM componenten zijn
geschreven in Visual Basic, dat het niet toe staat dat meerdere applicaties (of instanties van
applicaties) tegelijk een component gebruiken. Doe je dit toch, dan roep je allerlei problemen
over je af, die uiteindelijk kunnen leiden tot een crash van je applicatie of zelfs het systeem.
COM+ zorgt voor deze componenten dat slechts één applicatie tegelijk gebruik kan maken van een
component. Zo kunnen ontwikkelaars blijven programmeren alsof ze voor een enkele gebruiker schrijven,
terwijl ze in feite multi-user applicaties kunnen maken. Hier hangt mee samen dat COM+ ook aan object
instantie management doet. Dit wil zeggen dat COM+ ervoor zorgt dat er zonodig meerdere kopiëen van
een component beschikbaar zijn in een pool. Dit wordt daarom ook vaak object pooling genoemd.
Wanneer een applicatie een component nodig heeft, wordt dit toegewezen uit de pool. Is het klaar
met een component, dan wordt de component niet opgeruimd, maar weer teruggeplaatst in de pool, zodat
andere applicaties er gebruik van kunnen maken. Dit heeft als voordeel dat er veel minder overhead
is voor het instantiëren van componenten, en bovendien dat niet voor iedere lopende applicatie een
kopie van een component nodig is, doordat componenten gedeeld worden tussen applicaties. Het kan
echter zijn dat applicaties juist wel hun eigen componenten nodig hebben, en het liefst zo snel
mogelijk weer afsluiten. Dit komt bijvoorbeeld voor als een bestand open gehouden wordt door een
component. Voor die situatie biedt COM+ een andere techniek, die bekend staat als Just In Time
Activation (JITA). JITA zorgt ervoor dat een component dat een applicatie constant in gebruik
heeft alleen geactiveerd wordt op het moment dat het echt nodig is, en ook weer vrijgeeft zodra
dit kan. JITA is echter alleen interssant voor componenten die een betrekkelijk lage overhead
hebben om te creëren, het omgekeerde van waarvoor object pooling bedoeld is dus eigenlijk.
Naast de diensten die ervoor zorgen dat je als ontwikkelaar geen omkijken meer hebt naar transactie
management en schaalbaarheidsproblemen, biedt COM+ ook nog beveiliging op component niveau. Je kunt
een component namelijk zo instellen dat het alleen gebruikt mag worden door bepaalde gebruikers. Verder
kun je dat zelfde component zo instellen dat het uitgevoerd wordt onder een bepaalde gebruiker, of zich
voor doet als een bepaalde gebruiker. Dit heeft als voordeel dat je beveiligingsbeheer op een centrale
plek kunt doen, en dat je toegang kunt geven tot bepaalde functionaliteit via een component, terwijl
diezelfde functionaliteit niete direct beschikbaar is. Een database server is daarvan een mooi voorbeeld.
Het laatste wat je namelijk wilt doen is veel verschillende gebruikers daar toegang toe geven. Sterker
nog, eigenlijk wil je maar zelden dat gebruikers direct gegevens kunnen manipuleren in een database.
Dat moet over het algemeen via een applicatie. Door die functionaleit in een component te steken
dat werkt onder COM+, kun je toegang geven tot de database aan die component, maar niet aan de
afzonderlijke gebruikers. Die gebruikers geef je weer toegang tot de component. Men spreekt ook
wel van het delegeren van de beveiliging, omdat de daadwerkelijke toegang overgelaten wordt aan
een ander gebruikersaccount.
De laatste twee diensten die COM+ biedt hebben alles te maken met flexibiliteit: queued
components en events. Queued components biedt de mogelijkheid om functies asynchroon
aan te roepen. In feite wordt een aanroep in een qwachtrij geplaatst, en uitgevoerd
zodra dit kan. Dit betekent dat een component niet beschikbaar hoeft te zijn ten tijde
van de aanroep. Dit is bijvoorbeeld het geval als je een client applicatie meeneemt
naar een omgeving waar geen netwerk beschikbaar is. Bepaalde operaties kun je dan toch
uitvoeren, omdat die op een later tijdstip alsnog uitgevoerd worden, zonder dat je daar
iets voor hoeft te doen. De events dienst biedt een publisher-subscriber model voor
gebeurtenissen. Een component kan zich als het ware inschrijven op gebeurtenissen die
een ander component kan veroorzaken. Op het moment dat die gebeurtenis plaatvindt,
worden alle subscribers daarvan op de hoogte gesteld, en kan de nodig actie ondernomen
worden. COM+ maakt zonodig de objecten die zich ingeschreven hebben voor de gebeurtenis
aan.
De geschiedenis van COM+ Component Services
Sinds midden jaren negentig wordt op Windows geprogrammeerd op basis van het Component
Object Model (COM). COM componenten bevatten een speciale binaire interface die het
mogelijk maakt om gebruik te maken van de functionaliteit in een component, zonder dat
bekend is hoe die component intern in elkaar zit. Hierdoor kunnen componenten los van
elkaar ontwikkeld worden, en kunnen deze dynamisch aan elkaar gekoppeld worden. Zolang
alle componenten zich aan de gedefinieerde interface houden, kan de interne werking
daarvan veranderd worden zonder problemen op te leveren in applicaties die gebruik
maken van die componenten. Later ontwikkelde Microsoft Distributed COM (DCOM), zodat
het mogelijk werd om componenten aan te roepen die op een andere machine uitgevoerd
worden. Aan DCOM zitten wel wat haken en ogen. Wat gebeurt er bijvoorbeeld als een
andere machine (tijdelijk) down is, en hoe bepaal je of een applicatie die uitgevoerd
wordt op een andere machine gebruik mag maken een component? Een ander vraagstuk dat
indertijd belangrijk begon te worden was hoe men er voor zorgt dat allerlei operaties
die door verschillende componenten uitgevoerd worden als transactie uitgevoerd kunnen
worden. Met andere woorden, hoe zorg je ervoor dat alle operaties goed gaan, en dat als
er een operatie van meerdere fout gaat, de andere operaties ook niet uitgevoerd (of
teruggedraaid) worden. In een poging deze problemen op te lossen werd in 1998 Microsoft
Transaction Server (MTS) geïntroduceerd. Hoewel de naam suggereert dat MTS alleen voor
transactiemanagement zorgt, maar zoals je kunt lezen in dit artikel doet het veel meer.
MTS was een stap in de goede richting, maar door een gebrek aan integratie met het
operating systeem en COM/DCOM, had het een aantal beperkingen. Met de komst van Windows
2000 kon MTS veel beter geïntegreerd worden. Daarbij werden ook nog een aantal
mogelijkheden toegevoegd. Tegelijkertijd veranderde Microsoft de naam van MTS naar
COM+ Component Services. De meeste ontwikkelaars dachten namelijk dat MTS alleen nodig
was voor transacties, terwijl het veel meer in zn mars heeft, en dus ook in applicaties
die geen gebruik maken van transacties handig is. Omdat alle ontwikkelaars ondertussen
wel doordrongen waren van het belang van COM, werd de naam COM+ gebruikt, zodat men
sneller geneigd zou zijn naar MTS te kijken. COM+ Component Services is inmiddels een
belangrijk onderdeel geworden van wat wel Enterprise applicaties genoemd worden. Bij
Enterprise applicaties denken we meestal aan grootschalige applicaties voor grote
bedrijven, maar ook kleine bedrijfscritische applicaties kun je onder Enterprise
applicaties rekenen. Binnen .NET zijn de COM+ Component Services daarom bekend als
Enterprise Services, ook om te benadrukken dat .NET niets met COM te maken heeft.
|
Een .NET COM+ component
Als je een .NET component maakt, maak je normaal gezien een of meerdere classes, die
al dan niet afgeleid zijn van bestaande componenten. Wil je gebruik maken van COM+,
dan moeten de classes afgeleid zijn van de class ServicedComponent die deel uit maakt
van de System.EnterpriseServices namespace. De ServicedComponent class bevat alle
functionaliteit die nodig is om gebruikt te kunnen worden binnen COM+, en iedere
afgeleide class dus ook. Het skelet van een class die we kunnen gebruiken in COM+
ziet er in C# als volgt uit:
1: using System;
2: using System.EnterpriseServices;
3:
4: namespace WinNetDemo
5: {
6: public class ESDemoClass : ServicedComponent
7: {
8: //Code van de class hier
9: }
10: }
Om ervoor te zorgen dat COM+ altijd de correcte component gebruikt, moet je de assembly
waar de component onderdeel vanuit maakt nog wel voorzien van een zogenaamde strong
name. Dit is nodig om een component uniek te kunnen identificeren, en wordt door COM+
gebruikt om een CLSID te genereren die opgeslagen wordt in de Windows registry. Als een
applicatie gebruik maakt van de component, wordt de juiste versie gebruikt op basis van
die CLSID. Je kunt een strong name maken met sn.exe. Die maakt een bestandje met de
.snk extensie. Door in AssemblyInfo.cs (voor C#) een referentie te maken naar dat
bestandje zorg je dat de strong name gebruikt wordt als de component gecompileerd
wordt. Je doet dit door de volgende regel in AssemblyInfo.cs te plaatsen, ervan uitgaande
dat WinNetDemo.snk in de hoofdmap van je project staat in Visual Studio .NET (compileer
je handmatig, dan kan dit dus anders zijn):
[assembly: AssemblyKeyFileAttribute("..\\..\\WinNetDemo.snk")]
Nu is het component in principe klaar om in COM+ gebruikt te worden. Daarvoor dient het
echter wel geregistreerd te worden. Dit kan drie manieren, te weten handmatig met
RegSvcs.exe, automatisch op het moment dat een applicatie voor het eerste gebruik maakt
van de component, of door een aparte applicatie te maken waarmee je dit verzorgt. Het
is voor COM+ belangrijk dat een component op een bekende locatie staat. Automatisch
registreren is daarom niet iets wat je zomaar moet doen. Ook als je handmatig of via
een applicatie registreert, is het verstandig om de component eerst te registreren in
de Global Assembly Cache (GAC). Dit is een centrale plaats voor assemblies, die overigens
wel meerdere versies van dezelfde assembly kan bevatten. Alle assemblies die in de
GAC staan zijn door alle applicaties te gebruiken, en dat is voor COM+ eigenlijk wel
belangrijk. Wat je wilt voorkomen is dat applicaties hun eigen lokale versies van een
component gebruiken, en die afzonderlijk in COM+ registreren. Daarmee creëer je een
chaos die je liever wilt vermijden.
Configuratie
Componenten configureren doe je over het algemeen via de Component Services snap-in
van de Microsoft Management Console. Vanaf Windows 2000 is deze te vinden onder de
Administrative Tools. De applicaties die actief zijn onder COM+ zijn te vinden in de
COM+ Applications map die per computer beschikbaar is onder Component Services. Dit
zijn niet zo zeer applicaties, maar groepen van componenten. Omdat die over het algemeen
deel uitmaken van een applicatie zijn ze als zodanig gegroepeerd. Aan een applicatie
kun je componenten toekennen door ze toe te voegen in de Components map.

Afbeelding 1, Een applicatie in Component Services
Via de Roles map kun je bepalen welke Windows account groepen gebruik kunnen maken van
de componenten in de betreffende applicatie. In Afbeelding 1 zie je een voorbeeld van
een applicatie met één component daarin, en waarvan de applicatie alleen toegankelijk
is voor de Administrators groep. De eigenschappen van de applicatie zijn verder in te
stellen door met de rechter muisknop op de applicatie te klikken en te kiezen voor
Properties. Afbeelding 2 laat het scherm zien dat je dan te zien krijgt, nadat je
gekozen hebt voor de tab Identity. In die tab kun je instellen onder welke gebruiker
de component(en) uitgevoerd wordt. Dit kan een systeem account zijn, maar ook een
specifieke gebruiker. Overigens is deze optie alleen beschikbaar als de applicatie
ingesteld is als server, in plaats van library. In het eerste geval wordt de
betreffende applicatie in een apart proces van de client applicatie uitgevoerd, en kan
dus voor dat proces een andere gebruiker ingesteld worden. Zoals je ziet zijn er nog
veel meer opties, maar het vergt een stevig boek om op alle mogelijkheden van Component
Services in te gaan.

Afbeelding 2, Eigenschappen van een COM+ applicatie
Ieder component heeft ook eigenschappen die ingesteld kunnen worden. Je ziet hiervan
een voorbeeld van de tab Activation in afbeelding 3. De Activation instellingen bepalen
of object pooling en JIT Activation gebruikt worden. In dat laatste geval kun je ook
bepalen hoe groot de pool mag zijn.

Afbeelding 3, Eigenschappen van een component
Instellingen in code
In principe worden de instellingen van een component bepaald door de beheerder. Veel
van de instellingen hebben namelijk te maken met zaken die voor een ontwikkelaar niet
van belang horen te zijn. Object pooling en JIT Activation bijvoorbeeld zijn instellingen
die gebruikt worden bij het tunen van de performance, hetgeen geen ontwikkelactiviteit
is. Een instelling die wel van belang is voor een ontwikkelaar is het al dan niet
gebruiken van transacties. Het is eigenlijk gek dat een beheerder dit kan instellen,
want dit is een vereiste die uit de opbouw van een applicatie of component komt. Een
beheerder kan moeilijk bepalen of een applicatie wel of geen transacties moet gebruiken.
Het handige van .NET is dat je de code kunt voorzien van attributen die aangeven wat
de instelling van een component moet zijn. Wanneer een applicatie of component
geregistreerd wordt in COM+, neemt COM+ die instellingen over. Vervolgens kan een
beheerder daar eventueel nog wijzigingen in aanbrengen. Het biedt de ontwikkelaar
echter wel een manier om een basisinstelling te kiezen. Met name op het gebied van
transacties zou de beheerder deze instelling moeten respecteren. Voor andere instellingen
kunnen de basisinstellingen als richtlijn fungeren. De code hieronder laat een aantal
attributen zien die invloed uitoefenen op de instellingen van COM+.
1: [ObjectPooling(MinPoolSize = 3,MaxPoolSize = 10,CreationTimeout = 30)]
2: [Transaction(TransactionOption.Required)]
3: public class ESDemoClass : ServicedComponent
4: {
5: [AutoComplete]
6: public void DemoFunctie()
7: {
8: //Doe iets
9: }
10:
11: //Overige class code
12: }
In de code hierboven wordt ten eerste een instelling gegeven voor object pooling,
waarbij aangegeven wordt wat de limieten zijn, en na hoeveel milliseconden een timeout
plaats moet vinden. Ook wordt aangegeven dat het component alleen gebruikt kan worden
als onderdeel van een transactie. De functie DemoFunctie is voorzien van het attribuut
AutoComplete. Hiermee wordt aangegeven dat als alle code in die functie als normaal
uitgevoerd wordt, dat die functie dan kan aangeven aan de transactie dat hij succesvol
is uitgevoerd. Treedt er een fout op tijdens het uitvoeren van de functie, dan wordt
de transactie daar automatisch van op de hoogte gesteld. De ontwikkelaar hoeft zich
daardoor helemaal niet bezig te houden met de afhandeling van transacties, want dat
regelt .NET verder.
Veel meer
Er is nog veel meer te doen met COM+ en .NET dan hier behandeld. Wat als een paal boven
water staat is echter dat COM+ veel te bieden heeft aan .NET, en dat daarvan vanuit
.NET gebruik van te maken is zonder dat de ontwikkelaar uit zn weg moet gaan.
Enterprise Services is erop gericht om de afhandeling van COM+ zaken over te laten
aan .NET, zodat ontwikkelaars zich kunnen concentreren op de daarwerkelijke functionaliteit
van een applicatie.
Dit artikel is eerder verschenen in Windows & .NET Magazine Benelux, november 2003 (huidige naam NetOpus)
|