Projektowanie, Programowanie, Codzienność – BeniaminZaborski.com

13 października 2009

Spring.NET vs WCF

Filed under: How Can I Take ... — Tagi: , , , — Beniamin Zaborski @ 23:04

Tytuł artykułu zdradza nieco temat jaki chciałbym podjąć. Może samo versus jest nieco przewrotne, gdyż bardziej odpowiednie byłoby „Spring.NET a WCF” czy też po prostu „Spring.NET i WCF”. Tak naprawdę to tytuł powinien brzmieć „Spring.NET a WCF versus programista” ;). Obserwując programistów zaczynających przygodę ze Spring.NET i próbujących zintegrować z tym frameworkiem technologię WCF właśnie taki tytuł się nasuwa. Wielu programistów napotyka na problemy przy integracji tych rozwiązań. Zatem, moim zadaniem będzie zaprezentowanie prostej aplikacji pozwalającej hostować serwisy po technologii WCF w oparciu o Spring.NET.
W jednym z moich artykułów z serii „Ugryźć Spring.NET” poświęconych serwisom (cz.6) napisałem, że zmiana technologii hostowania serwisów wymagać będzie jedynie zmian w konfiguracji. W dużej mierze jest to oczywiście prawda. Jednak są pewne niuanse, które wymagają wyjaśnienia. W przykładzie w tamtym artykule serwisy były hostowane za pomocą .NET Remotingu, tu będzie to WCF.
A teraz uwaga skierowana w stronę wszystkich tutoriali do WCF jakie widziałem. Uważam, że wszystkie te tutoriale uczą skrajnie niepraktycznego podejścia do jednej z kwestii – client proxy. Chodzi tu o generowanie klas proxy klienta za pomocą bądź to bezpośrednio środowiska Visual Studio, bądź narzędzia svcutil.exe. Jak dla mnie wiąże się z tym podstawowa niedogodność, iż w trakcie tworzenia aplikacji mój serwis musi być już hostowany, abym mógł skorzystać z dobrodziejstw narzędzia svcutil.exe. Poza tym każda zmiana w serwisie wymaga ponownego przegenerowania. Koszmar!!! Wady takiego rozwiązania można by jeszcze mnożyć – serwisy są „mało abstrakcyjne” czyli zbyt powiązane z implementacją opartą na WCF.
Proste podejście do którego się już przyzwyczaiłem to osobne assembly z interfejsem modelu aplikacji i osobne assembly z implementacją tego modelu (czytaj serwisów).
Dlaczego taki model, uważany nie tylko przeze mnie za właściwy, ma być zburzony przez WCF? Ależ wcale nie musi! Gdyby tylko w tych tutorialach więcej pisano o klasie ChannelFactory i metodzie CreateChannel …
Z tego rozwiązania korzysta właśnie Spring.NET. Dzięki temu migrując serwisy naszej aplikacji z .NET Remotnigu do WCF nie burzymy naszej aplikacji, a jedynie dokonujemy zmian w konfiguracji. Pozostaje tu oczywiście jedna kwestia do wyjaśnienia, czyli atrybutów WCF-a, tj. ServiceContract oraz OperationContract. One niestety muszą być użyte, więc to będzie cała zmiana w kodzie aplikacji – reszta to config. Nasze obiekty DTO są zapewne już opatrzone atrybutem Serializable i wcale nie musimy tego zmieniać na DataContract.
Wyjaśniłem chyba już trochę, a zatem czas na przykład. Przykład jest trywialny.
Solution składa się z czterech projektów:

  • interfejs modelu (BeezDev.SpringWCFApplication.Model.Interface)
  • implementacja modelu (BeezDev.SpringWCFApplication.Model)
  • konsolowa aplikacja hostująca serwisy aka server (BeezDev.SpringWCFApplication.Server)
  • okienkowa aplikacja klient (BeezDev.SpringWCFApplication.Client)

Aplikacja posiada jeden serwis HelloService z jedną metodą SayHello przyjmującą jako parametr jeden obiekt DTO i zwracającą inny typ obiektu DTO. Jakże wyszukana logika mówi: „podaj mi swój login, a zostaniesz przywitany”. Aplikacja serwera posiada referencję do interfejsu modelu jak i jego implementacji, natomiast już klient posiada tylko referencję do interfejsu modelu.
Przyjrzyjmy się najpierw konfiguracji serwera. Nie będę oczywiście omawiał całości konfiguracji Spring.NET, a jedynie te elementy które są istotne w kontekście WCF. Pierwsza sprawa to definicja serwisu w kontenerze IoC Springa.
Generalnie przy migracji z .NET Remoting ona istnieje. Jedyna zmiana, której ewentualnie musimy dokonać, to oznaczyć serwis aby nie był uruchamiany jako singleton (singleton=”false”). Jak podaje dokumentacja Spring.NET ten typ aktywacji obiektu nie współpracuje poprawnie z technologią WCF. Przyjmijmy to jako pewnik i na tym etapie nie wnikajmy w szczegóły.
Cała moc Springa drzemie w eksporterach serwisów, a więc należy zdefiniować odpowiedni dla WCF:


<object id=”helloServiceHost” type=”Spring.ServiceModel.ServiceExporter, Spring.Services”>
  <property name=”TargetName” value=”helloService” />
</object>

Nie ma tu nic nowego, poza szczególnym typem eksportera serwisu Spring.ServiceModel.ServiceExporter.
Od serwera wymaga się hostowania naszego serwisu i do tego służy klasa ServiceHost. To kolejna zmiana w kodzie jaką musimy wykonać w stosunku do .NET Remoting. Zakładając, że aplikacja hostująca nie jest częścią modelu aplikacji, a więc ta zmiana się nie liczy;).
Teraz klient czyli to najciekawsze z punktu widzenia WCF. Zmiany w kodzie? Nie! Żadnych zmian! Aplikacja działa tak samo, tj. pobiera instancję serwisu z kontenera IoC Spring-a i wywołuje jego metody. Zatem wszystkie zmiany ograniczą się do pliku konfiguracyjnego.
Definiujemy ChannelFactory dla naszego serwisu:


<object id=”helloServiceChannelFactory” type=”System.ServiceModel.ChannelFactory&lt;BeezDev.SpringWCFApplication.Model.IHelloService>, System.ServiceModel”>
  <constructor-arg name=”endpointConfigurationName” value=”tcpEndpoint” />
</object>

Jako parametr generyczny podajemy typ naszego serwisu i kolejna rzecz wymagająca wyjaśnienia to argument konstruktora. Tutaj przekazujemy nazwę endpointa-a z konfiguracji WCF-a. O tym jeszcze wspomnę później.

Następnie definicja naszego serwisu:


<object id=”helloService” type=”BeezDev.SpringWCFApplication.Model.IHelloService, BeezDev.SpringWCFApplication.Model.Interface”
  factory-object=”helloServiceChannelFactory”
  factory-method=”CreateChannel” />

Jako klasę fabrykującą wskazujemy obiekt zdefiniowany wcześniej, a metoda fabrykująca to oczywiście CreateChannel.
To wszystko! No prawie wszystko;). Pozostaje kwestia konfiguracji samego WCF, która jest niejako poza tematem tego artykułu. Wspomnę tylko, że konfiguracji dokonujemy w tradycyjny sposób, tj. w sekcji system.serviceModel pliku app.config. W przykładzie użyłem hostowania serwisów po protokole TCP z binarną serializacją. Po szczegóły związane z cała magią konfiguracji WCF-a tzw. ABC odsyłam do dokumentacji.

Pełne solution tutaj. Miłej zabawy!

1 komentarz »

  1. A ja sie nie zgodze…

    Komentarz - autor: johny-max — 25 listopada 2009 @ 11:30


RSS feed for comments on this post. TrackBack URI

Dodaj komentarz

Stwórz darmową stronę albo bloga na WordPress.com.