XML Schema jest bodajże najlepszym sposobem walidacji dokumentów XML. Model zastosowany w przypadku tego meta-języka pozwala na tworzenie złożonych konstrukcji. W oparciu o niego można budować własne rozszerzenia czy też zagnieżdżać w sekcjach xsd:appinfo dodatkowe metadane. Dzisiaj jednak nie o tym, a o wzorcach projektowych. Sam się zdziwiłem gdy trafiłem na artykuł Introducing Design Patterns in XML Schemas. W życiu się nie zastanawiałem czy to co piszę w XSD ma coś wspólnego z wzorcami czy nie. Sun wyprzedził w tym momencie chyba wszystkich. 🙂
Wzorce, które zostały wymienione we wspomnianym artykule odnoszą się do powiązania definiowanych typów z definiowanymi elementami. Ciężko mi się zgodzić z tym, że wybór wzorca jest krytyczny przy projektowaniu schematu, ponieważ schemat zazwyczaj ma przeznaczenie już w chwili pisania i zazwyczaj nie możemy powiedzieć, zrobimy to wzorcem X, ponieważ sam nasuwa się wzorzec Y. Ale to tak tylko moim zdaniem.
Tabelka poniżej prezentuje zawartość przeniesioną ze strony Suna. Zawiera ona 4 najpopularniejsze wzorce. Dwa najczęściej spotykane w internecie to Venetian Blind oraz Garden of Eden ze względu na to, że są bardzo podatne na ponowne użycie.
Wzorzec | Charakterystyka |
---|---|
Russian Doll, przykład | Zawiera jeden element globalny, pozostałe są lokalne. |
|
|
Salami Slice, przykład | Wszystkie elementy są globalne, stąd każdy może być użyty w charakterze root node’a. |
|
|
Venetian Blind, przykład | Pochodna Russian Doll, zawiera jeden element globalny, pozostałe są lokalne |
|
|
Garden of Eden, przykład | Połączenie Venetian Blind oraz Salami Slice. Wiele elementów globalnych, wiele typów publicznych. Wiele kandydatów na root node. |
|
|
Źródło: Sun Developers Network |
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.sun.com/point/russiandoll" xmlns:tns="http://schemas.sun.com/point/russiandoll" elementFormDefault="qualified"> <xsd:element name="Line"> <xsd:complexType> <xsd:sequence> <xsd:element name="PointA"> <xsd:complexType> <xsd:attribute name="x" type="xsd:integer"/> <xsd:attribute name="y" type="xsd:integer"/> </xsd:complexType> </xsd:element> <xsd:element name="PointB"> <xsd:complexType> <xsd:attribute name="x" type="xsd:integer"/> <xsd:attribute name="y" type="xsd:integer"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.sun.com/point/salami" xmlns:tns="http://schemas.sun.com/point/salami" xmlns="http://schemas.sun.com/point/salami" elementFormDefault="qualified"> <xsd:element name="PointA"> <xsd:complexType> <xsd:attribute name="x" type="xsd:integer"/> <xsd:attribute name="y" type="xsd:integer"/> </xsd:complexType> </xsd:element> <xsd:element name="PointB"> <xsd:complexType> <xsd:attribute name="x" type="xsd:integer"/> <xsd:attribute name="y" type="xsd:integer"/> </xsd:complexType> </xsd:element> <xsd:element name="Line"> <xsd:complexType> <xsd:sequence> <xsd:element ref="PointA"/> <xsd:element ref="PointB"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.sun.com/point/venetianblind" xmlns:tns="http://schemas.sun.com/point/venetianblind" xmlns="http://schemas.sun.com/point/venetianblind" elementFormDefault="qualified"> <xsd:complexType name="PointType"> <xsd:attribute name="x" type="xsd:integer"/> <xsd:attribute name="y" type="xsd:integer"/> </xsd:complexType> <xsd:element name="Line"> <xsd:complexType> <xsd:sequence> <xsd:element name="PointA" type="PointType"/> <xsd:element name="PointB" type="PointType"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.sun.com/point/gardenofeden" xmlns="http://schemas.sun.com/point/gardenofeden" elementFormDefault="qualified"> <xsd:complexType name="PointType"> <xsd:attribute name="x" type="xsd:integer"/> <xsd:attribute name="y" type="xsd:integer"/> </xsd:complexType> <xsd:complexType name="LineType"> <xsd:sequence> <xsd:element ref="PointA"/> <xsd:element ref="PointB"/> </xsd:sequence> </xsd:complexType> <xsd:element name="PointA" type="PointType"/> <xsd:element name="PointB" type="PointType"/> <xsd:element name="Line" type="LineType"/> </xsd:schema>
Pod koniec maja świetnie spędziłem czas w Wielkiej Brytanii dostarczając consulting. Tuż po nim zacząłem myśleć o podzieleniu się ideą aplikacji middleware zbudowanej na ActiveMQ z funkcjami Camela. Spędziłem kilka dni tworząc wystarczający przykład.
Middleware jest ogólnym terminem traktującym o oprogramowaniu które jest pewnego rodzaju pośrednikiem między systemami. Po cóż? – możesz zapytać. Generalnie ponieważ komunikacja pomiędzy punktami nie jest najlepsza do budowania większych aplikacji, co więcej niektóre komponenty pomiędzy komunikującymi pozwalają wstrzykiwać nową logikę bez zmieniania systemów komunikujących się. Czy możesz wyobrazić sobie sytuację gdzie wiele systemów tworzy komunikaty i wielu konsumentów tych komunikatów stworzonych w różnych językach? To jest typowy scenariusz gdzie middleware będzie użyteczne.
Istnieje wiele narzędzi middleware i kilka ich kategorii, w tym wpisie dowiemy się jak używać ActiveMQ do budowania message oriented middleware. Co oznacza termin MOM? To, że mamy asynchroniczną komunikację bez bezpośrednich wywołań metod. Producent nic nie wie o konsumencie i na odwrót. Jeśli jesteś zainteresowany MOM-ami – zajrzyj do książki “ActiveMQ in Action” (napisanej przez commiterów ActiveMQ) z wydawnictwa Manning, w której termin ten jest opisany szerzej.
Read the rest of this entry »
W tym wpisie zostanie omówiony proces OSGi-fikacji artefaktów, który przechodziłem gdy uruchamiałem prostą usługę na ServiceMix, która miała śledzić zewnętrzny RSS i pobierać z niego wpisy. Postanowiłem skorzystać z camel-rss. Przykłady które były do niego załączone są wystarczające by stworzyć odpowiedniego konsumenta…
Read the rest of this entry »
Do opublikowania tego postu zachęcił mnie Jacek Laskowski swym postem pod tytułem W piątek 4Developers ze mną z Enterprise OSGi i in.
Bardzo się cieszę że na 4Developers (na którym niestety mnie nie będzie) temat Enterprise OSGi będzie poruszony, ponieważ jak się zdaje jest to nieuchronny kierunek rozwoju Javy. Pod wpływem słów Jacka zacząłem się zastanawiać nad długofalowymi efektami jakie OSGi ma wnieść do developmentu.
Hałas który obecnie jest wokół OSGi w przybiera konkretne kształty w postaci projektów takich jak Aries czy Gemini. Obydwa projekty skupiają się nad ostatnimi draftami OSGi R4 V4.2 i mają na celu udostępnienie technologii takich jak JNDI, JPA i JMX wewnątrz kontenerów OSGi. Zacznijmy jednak od początku..
JAR-hell occurs when software is deployed into a runtime environment which is unsuitable, but nothing other than full integration testing would detect this. Having multiple software packages dependent upon the same piece of software, with unpredictable incompatibilities, is pure hell. Ensuring the compatibility of a variety of dependent packages is duanting, doing it amongst the variety supported by a hierarchy of complex class loaders, is inhuman.
Źródło Apache Depot
Czyli w skrócie – piekło zaczyna się robić gdy pojawiają się niekompatybilności między bibliotekami w poprawnym środowisku. Co więcej owe niekompatybilności można wykryć dopiero po dogłębnych testach we wszystkich środowiskach w których ma działać aplikacja.
W przypadku OSGi wszystkie zależności są przewidywalne, co więcej nie uda się nam uruchomić paczki bez jej zależności – stąd teoretycznie nigdy nie powinniśmy widzieć ClassNotFoundException. Nie uda nam się również uruchomić naszego bundle jeśli powstanie konflikt w używanych zależnościach. Przykład z życia wzięty – mamy bundle zależące od camel-activemq oraz activemq-core. Pierwszy z nich pozwala na import spring-jms w wersji < 4.0, natomiast drugi w wersji < 2.6. Jeśli do tego mamy dwie wersje bundle spring-jms: 2.5.6 oraz 3.0.0 to mamy klapę. Naszej paczki nie da się wystartować ponieważ otrzymamy "Packages usage conflict". Zostaliśmy ochronieni przed JAR Hellem kosztem zablokowania kodu nawet jeśli zależność była opcjonalna.
Problem wydaje się trywialny – teoretycznie to są dwie różne wersje Springa, nie da się zaprzeczyć że 2.5.6 != 3.0.0. W praktyce jednak zmiany w spring-jms były tak niewielkie że można bez problemu uruchomić activemq-core z nową wersją. W takim wypadku jesteśmy zmuszeni do czekania na nową wersję ActiveMQ, która będzie pozwalała na korzystanie ze Springa 3.0 bądź samodzielnie zmodyfikować manifesty. Obydwa rozwiązania są równie złe – jedno to czekanie, drugie to tworzenie nowej dystrybucji ActiveMQ.
Co w takim wypadku możemy zrobić? Możemy użyć serwisów OSGi, które pozwalają na oddzielenie implementacji od interfejsu, dzięki czemu możemy połączyć dwie wersje bibliotek za fasadą w postaci ServiceReference. Tutaj jednak może pojawić się inny problem – mianowicie część bibliotek które lubią dostęp do ClassLoaderów może skutecznie protestować – na przykład Hibernate czy Open JPA. Dla przykładu diagram obrazujący kolejny z życia wzięty przypadek:
W tym przypadku usiłowałem stworzyć działającą usługę która zapisywała by przychodzące komunikaty w bazie danych. Może parę słów o tym, który bundle co robi:
Całość komunikacji odbywała się z JMS w trybie request-reply dzięki Apache Camel. Po bardzo długich “walkach” poniższą strukturę udało się uruchomić pod OSGi. Ostatecznie całość działa z Hibernate w układzie takim jak poniżej.
Z diagramu wyrzuciłem paczki które nie są istotne takie jak driver JDBC czy Commons ConnectionPool. Jedyny mankament na jaki trafiłem wiąże się z DAO Service, mianowicie bundle który go eksportuje poprzez Spring-DM musi zadeklarować widoczność wszystkich swoich klas dla paczki która będzie korzystać z usługi co jak by nie patrzeć jest drobnym wypaczeniem fasady jaką ma być ServiceReference. Niestety po 2 tygodniach poświęconych na uruchomienie JPA w OSGi nie siliłem się na elegancję.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd "> <osgi:reference id="dataSource" interface="javax.sql.DataSource" /> <osgi:service id="exchangeDAOExporter" ref="exchangeDAO" context-class-loader="service-provider" interface="org.code_house.dataaccess.ExchangeDAO" /> </beans>
Problem jaki powstaje z OSGi to metadane. Do tej pory – jeśli zarządzałem zależnościami do bibliotek robiłem to przez dependencyManagement Mavena, dzięki któremu rozwiązywałem wszystkie konflikty. OSGi jednak nie wiąże się z Mavenem ponieważ są to dwa różne obszary o zgoła innym funkcjonowaniu – OSGi to runtime, Maven to build time. Dopóki nie zapanuje harmonia pomiędzy tymi dwoma uruchamianie czegokolwiek w OSGi będzie katorgą. Należy do tego dodać jeszcze jeden element związany z OSGi – mianowicie OSGi Bundle Repository (OBR), a OBR nijak się ma do repozytoriów Mavena przez co rozbieżności tylko się nasilają.
Aby temu zapobiegać najpopularniejsze istniejące repozytoria SpringSource Enterprise Bundle Repository oraz ServiceMix 4 Bundles repository – publikują artefakty w repozytoriach Mavena. Problem w tym, że część artefaktów jest powielona. Tak jak kiedyś były 3 wersje Java Persistence API tak teraz dochodzą kolejne dwie – z manifestami OSGi. Czy ktoś wspominał o piekle?
Należy również dodać że nie każdy JAR który ląduje w OSGi jest traktowany tak samo – oprócz standardowych bundli są również fragmenty, które są świetnym rozwiązaniem, jednakże początkowo potrafią przysporzyć wielu problemów. Cały trik sprowadza się do tego, że fragmenty mają wspólny class loader z paczką do której są przypięte.
Po całych tych wywodach na temat problemów z OSGi pora na to co ma ono nam dać – przenośność. Podobnie jak Java EE 6 z profilami tak OSGi ma zapewnić większą przenośność klocków pomiędzy środowiskami. Wyobrażacie sobie, że można przenieść aplikację z kontenera servletów na serwer aplikacyjny bez modyfikacji? Albo usługę z szyny integracyjnej na kontener servletów? Niedorzeczne, ale z OSGi możliwe do wykonania. Wystarczy zainstalować wszystkie wymagane bundle i całość będzie działać.
Oczywiście naiwna była by wiara w to, że tak będzie. Każda specyfikacja która powstaje dla Javy ma standaryzować i ujednolicać środowiska. W praktyce jednak każda z nich staje się punktem wyjściowym do rozwoju nowych produktów. Każdy dostawca oferuje zgodność ze specyfikacją plus coś. Nie twierdzę, że to złe, ponieważ polaryzacja rynku oprogramowania jest tak samo potrzebna jak wolny rynek, należy się jednak wystrzegać monopolistów a w przypadku oprogramowania również vendor locków.
Patrzę na OSGi z nadzieją ponieważ w moim mniemaniu jest to przedłużenie idei jaką niosła specyfikacja Java Business Integration. Propozycja JBI 2.0 spotkała się z krytyką ze strony IBM oraz BEA Systems zasłaniających się tym, że istnieje SCA. Problem w tym, że obydwie specyfikacje traktują o innych warstwach integracji – SCA gwarantuje przenośność usług, podczas gdy JBI miało zapewnić przenośność komponentów i komunikacji między nimi. SCA i JBI mogą a nawet powinny iść w parze. Teoria JBI mówiła o możliwości uruchomienia servicemix-cxf-bc (zgodnego z JBI) na Open ESB, w praktyce okazywało się to jednak bardzo trudne. Dzięki OSGi/Enterprise OSGi stanie się to łatwiejsze.
W ciągu kilku najbliższych lat trend OSGi dzięki zainteresowaniu wielkich korporacji będzie rósł w siłę. Trzymam kciuki by Enterprise OSGI przyniosło więcej korzyści niż tylko zbawienie od JAR Hella.
Dnia 23 lutego w ramach Warszawa JUG miałem przyjemność wraz z Tomkiem Nurkiewiczem prezentować narzędzia integracyjne z otwartym kodem źródłowym. Tomek przedstawił Mule ESB, podczas gdy ja zająłem się Apache ServiceMix i Apache Camel. Ze względu na objętość przykładu ten wpis będzie jedynie wprowadzeniem do konsoli.
Niestety podczas prezentacji nie udało mi się uruchomić przykładu na “szynie” – ponieważ uniemożliwiły to zależności do bibliotek których nie miałem zapisanych lokalnie. Drugim mym przeciwnikiem był czas – nie było wielu chętnych by słuchać po 2h tłumaczeń dlaczego się nie udało 🙂 Na problem z zależnościami stworzyłem rozwiązanie i zgłosiłem je do Karaf-a (FELIX 2141). W przyszłej wersji – 1.6 – wszyscy będą mogli skorzystać z polecenia features:info -t które wyświetli całe drzewko zależności potrzebnych do zainstalowania nowych funkcjonalności.
Do uruchomienia przykładów potrzebować będziemy dwóch paczek – pierwsza to Apache ServiceMix, druga to Apache Maven. Ze swojej strony polecam pobranie FUSE ESB 4.2, produktu który jest oparty o ServiceMix. Zgodnie z moimi zapowiedziami od tej wersji FUSE Source wprowadza pełne wsparcie produkcyjne dla ServiceMix 4. Jeśli nie masz zainstalowanego Mavena i nigdy tego nie robiłeś zajrzyj na wiki Code-House: Wprowadzenie do Maven 2
Po pobraniu odpowiedniej wersji należy ją rozpakować do wybranego folderu. Szynę uruchamiamy skryptem servicemix.bat. Jeśli wszystko przebiegło poprawnie naszym oczom powinien ukazać się obrazek jak poniżej:
E:toolsprogressfuse-esb4.2.0-bbin>servicemix.bat ____ _ __ __ _ / ___| ___ _ ____ _(_) ___ ___| / (_)_ __ ___ / _ '__ / / |/ __/ _ |/| | / / ___) | __/ | V /| | (_| __/ | | | |> < |____/ ___|_| _/ |_|______|_| |_|_/_/_ Apache ServiceMix (4.2.0-fuse-01-00) Hit '' for a list of available commands and '[cmd] --help' for help on a specific command. karaf@root>
Od tej chwili mamy do dyspozycji konsolę administracyjną. Aby zwiększyć jej użyteczność wykonujemy następujące polecenia:
karaf@root> osgi:install wrap:mvn:http://download.java.net/maven/2!net.java.dev.jna/jna/3.1.0
Bundle ID: 134
Spowoduje to pobranie z repozytorium Mavena (http://download.java.net/maven/2) biblioteki JNA w wersji 3.1.0. Nie musimy oczywiście określać za każdym razem adresu repozytoriów, ale o tym nieco później. Prefix wrap: spowoduje wygenerowanie manifestu OSGi na podstawie zawartości pobranej biblioteki. Jest on konieczny ponieważ JNA nie dostarcza potrzebnych danych do uruchomienia w środowisku OSGi.
karaf@root> osgi:install mvn:http://jansi.fusesource.org/repo/release!org.fusesource.jansi/jansi/1.2
Bundle ID: 135
Druga biblioteka wykorzystuje JNA i umożliwia kolorowanie tekstu w konsoli windowsowej zgodnie z ANSI, czyli tak jak w standardowych terminalach Unix-a. Po zainstalowaniu tych dwóch rzeczy pora zaprząc je do pracy. Poniżej filtrujemy listę zainstalowanych rzeczy po słowie Console.
karaf@root> list|grep Console [ 10] [Active ] [Created ] [ ] [ 30] Apache Felix Karaf :: Shell Console (1.4.0.fuse-01-00) karaf@root> refresh 10
Numer 10 oznacza id paczki OSGi, tekst Active to stan paczki a tekst Created informuje o stanie kontekstu blueprint, czwarty bloczek to stan kontekstu Springa, numer 30 to start level paczki a w ostatnim nawiasie mamy wersję. Sporo informacji jak na jedną linijkę, nieprawdaż? Blueprint to standaryzowanie tego czym jest Spring i Spring DM, także można korzystać zamiennie bądź z jednego bądź z drugiego rozwiązania. Ciekawe porównanie funkcjonalności obu rozwiązań – Spring DM oraz Blueprint opublikował kilka dni temu Guillaume Nodet na swoim blogu we wpisie Spring-DM, Aries Blueprint and custom namespaces. Apache Camel od wersji 2.3 będzie wspierał Blueprint (CAMEL-2022).
____ _ __ __ _ / ___| ___ _ ____ _(_) ___ ___| / (_)_ __ ___ / _ '__ / / |/ __/ _ |/| | / / ___) | __/ | V /| | (_| __/ | | | |> < |____/ ___|_| _/ |_|______|_| |_|_/_/_ Apache ServiceMix (4.2.0-fuse-01-00) Hit '<tab>' for a list of available commands and '[cmd] --help' for help on a specific command. karaf@root>
Teraz wykonanie poleceń z filtrem grep spowoduje podświetlenie szukanej frazy:
karaf@root> list |grep Console [ 10] [Active ] [Created ] [ ] [ 30] Apache Felix Karaf :: Shell Console (1.4.0.fuse-01-00)
Takie małe udogodnienie przy przeglądaniu dłuższych rezultatów jest nieocenione.
Polecenia w Apache Karaf są podzielone na kilka grup, które ułatwiają zarządzanie. Pierwszą grupą jest OSGi.
Polecenie | Przeznaczenie |
---|---|
list | Wyświetlenie listy zainstalowanych paczek |
ls [bundle id] | Wyświetlenie usług eksportowanych przez paczkę. |
ls -u [bundle id] | Wyświetlenie usług używanych przez paczkę. |
headers [bundle id] | Wyświetlenie manifestu paczki. |
start [bundle id] | Uruchomienie paczki o danym ID. |
stop [bundle id] | Zatrzymanie paczki o danym ID. |
restart [bundle id] | Zatrzymanie i wystartowanie paczki o danym ID. |
update [bundle id] | Aktualizacja paczki. |
refresh [bundle id] | Odświeżenie importów paczki a także przeładowanie kontekstu Spring-DM. |
install [url] | Zainstalowanie nowej paczki. |
uninstall [bundle id] | Odinstalowanie paczki. |
shutdown | Zatrzymanie kontenera. |
bundle-level [bundle id] [startLevel] | Ustawienie start levelu dla paczki. |
start-level |
Kiedy znamy już listę poleceń nie pozostaje nic innego jak je wypróbować. 🙂 Checkout przykładowego kodu z SVN pozwoli wykonać nam kilka ćwiczeń. Po wykonaniu polecenia mvn clean install w repozytorium Mavena są JARy które, naturalnie, chcemy zainstalować. Rezultat jaki powinniśmy zobaczyć w konsoli to:
[INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] ------------------------------------------------------------------------ [INFO] Money transfer ServiceMix example ..................... SUCCESS [2.028s] [INFO] Money transfer :: API ................................. SUCCESS [3.182s] [INFO] Money transfer :: POI bundle .......................... SUCCESS [7.504s] [INFO] Money transfer :: Internal ............................ SUCCESS [0.093s] [INFO] Money transfer :: Internal :: CSV ..................... SUCCESS [4.399s] [INFO] Money transfer :: Internal :: XLS ..................... SUCCESS [2.823s] [INFO] Money transfer :: Internal :: Mail .................... SUCCESS [2.309s] [INFO] Money transfer :: Internal :: Splitter ................ SUCCESS [0.936s] [INFO] Money transfer :: Internal :: Routes .................. SUCCESS [1:21.241s] [INFO] Money transfer :: External ............................ SUCCESS [0.016s] [INFO] Money transfer :: External :: Customer ................ SUCCESS [3.182s] [INFO] Money transfer :: External :: Bank .................... SUCCESS [2.059s] [INFO] Money transfer :: External :: Validator ............... SUCCESS [2.918s] [INFO] Money transfer :: Features ............................ SUCCESS [0.171s] [INFO] ------------------------------------------------------------------------ [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1 minute 54 seconds [INFO] Finished at: Mon Mar 22 10:47:27 CET 2010 [INFO] Final Memory: 127M/341M [INFO] ------------------------------------------------------------------------
Może teraz kilka słów o modułach które są widoczne w Mavenie.
Moduł | Ścieżka Maven ID |
Przeznaczenie |
---|---|---|
Money transfer :: API | api org.code-house.samples/api |
API systemów zewnętrznych oraz POJO wykorzystywane do komunikacji. |
Money transfer :: POI bundle | poi org.code-house.samples/poi |
Bundle zawierający bibliotekę Apache POI oraz wszystkie jej zależności z Manifestem OSGi pozwalającym na jej uruchomienie na szynie. |
Money transfer :: Internal :: CSV | internal/csv org.code-house.samples.internal/csv |
Paczka zawierająca implementację procesora przetwarzającego pliki CSV na POJO MoneyTransfer. |
Money transfer :: Internal :: XLS | internal/xls org.code-house.samples.internal/xls |
Paczka zawierająca implementację procesora przetwarzającego pliki XLS na POJO MoneyTransfer. |
Money transfer :: Internal :: Mail | internal/mail org.code-house.samples.internal/mail |
Paczka z kodem dzielącym przychodzący mail z załącznikami na pojedyncze wiadomości które można przetworzyć jako XLS bądź CSV. |
Money transfer :: Internal :: Splitter | internal/splitter org.code-house.samples.internal/splitter |
Paczka z kodem odpowiedzialnym za rozdzielanie listy obiektów MoneyTransfer na listę wiadomości. |
Money transfer :: Internal :: Routes | internal/routes org.code-house.samples.internal/routes |
Główna paczka z definicjami routingu |
Money transfer :: External :: Customer | external/customer org.code-house.samples.external/customer |
Implementacja WebService odpowiedzialnego za pobieranie danych klienta na podstawie numeru rachunku bankowego. |
Money transfer :: External :: Bank | external/bank org.code-house.samples.external/bank |
Implementacja usługi zwracającej informację o nazwie banku na podstawie numeru rachunku. |
Money transfer :: External :: Validator | external/validator org.code-house.samples.external/validator |
Usługa weryfikująca czy MoneyTransfer jest poprawny. |
Money transfer :: Features | features org.code-house.samples/features |
Moduł zawierający opcjonalny deskryptor do uruchomienia modułów. |
Jak widać dwa główne obszary projektu są skupione w katalogach internal oraz external. Ten pierwszy zawiera implementacje ściśle związaną z usługami natomiast drugi to “zatyczki” emulujące działanie systemów zewnętrznych. Drobna nota – kolumna Maven ID nie zawiera informacji o wersji – w każdym module jest to 1.0.0.SNAPSHOT.
Aby zainstalować któryś bundle przechodzimy do konsoli ServiceMix’a i wykonujemy takie polecenia:
karaf@root> install -s mvn:org.code-house.samples/api/1.0.0.SNAPSHOT Bundle ID: 210 karaf@root> features:install camel-jetty karaf@root> install -s mvn:org.code-house.samples.external/customer/1.0.0.SNAPSHOT Bundle ID: 211
Po wykonaniu tych poleceń powinien być uruchomiony Web Service którego WSDL znajduje się pod adresem http://localhost:9001/CustomerWs?wsdl. Przełącznik -s w przypadku polecenia install powoduje że po zainstalowaniu bundle zostanie wystartowany. Polecenie features-install camel-jetty jest potrzebne nie ze względu na to że kolejna paczka korzysta z Camela, dzięki jego wykonaniu zostanie zainstalowane Jetty, z którego korzysta CXF.
Kolejne paczki instalujemy analogicznie:
karaf@root> features:install camel-activemq karaf@root> install -s mvn:org.code-house.samples.external/validator/1.0.0.SNAPSHOT Bundle ID: 215 karaf@root> install -s mvn:org.code-house.samples.external/bank/1.0.0.SNAPSHOT Bundle ID: 217
Rozszerzenie camel-activemq jest rozszerzeniem modułu camel-jms które pozwala na nieco wydajniejszą pracę z ActiveMQ.
Maven jako narzędzie do budowania korzysta z określonego schematu składowania bibliotek które następnie są automatycznie pobierane. Karaf, który jak wspomniałem podczas prezentacji, wyłonił się z projektu ServiceMix Kernel korzysta z biblioteki Pax URL. Dzięki temu z marszu mamy dostęp do standardowych repozytoriów Mavena, co jednak gdy mamy swoje repozytorium, które zawiera tylko nasze artefakty?
Otwieramy plik etc/org.ops4j.pax.url.mvn.cfg i dodajemy w nim co trzeba. Moja standardowa konfiguracja wygląda następująco:
org.ops4j.pax.url.mvn.settings=E:/tools/maven-2.2.1/conf/settings.xml org.ops4j.pax.url.mvn.localRepository=E:/repository org.ops4j.pax.url.mvn.defaultRepositories=file:${karaf.home}/${karaf.default.repository}@snapshots org.ops4j.pax.url.mvn.repositories= http://repo1.maven.org/maven2, http://repo.fusesource.com/maven2, http://repo.fusesource.com/maven2-snapshot@snapshots@noreleases, http://repository.apache.org/content/groups/snapshots-group@snapshots@noreleases, http://repository.ops4j.org/maven2, http://svn.apache.org/repos/asf/servicemix/m2-repo, http://repository.springsource.com/maven/bundles/release, http://repository.springsource.com/maven/bundles/external, http://repository.code-house.org/content/groups/release, http://repository.code-house.org/content/groups/snapshot@snapshots@noreleases, http://jansi.fusesource.org/repo/release
Dzięki temu PAX w pierwszej kolejności będzie skanował katalog E:/repository zamiast standardowego ~/.m2/repository. Jeśli któreś z repozytoriów wymaga autoryzacji adres powinien wyglądać następująco:
http://user:pass@jansi.fusesource.org/repo/release
Mam nadzieję że wpis ten przybliży chociaż w niewielkim stopniu ServiceMix 4 oraz Karafa. W przyszłym wpisie, którego daty publikacji nie sposób przewidzieć zostaną dokładniej omówione polecenia z grupy features. Póki co życzę miłej zabawy z konsolą. 🙂 W razie pytań, niejasności i problemów – proszę o komentarze.
W nawiązaniu do poprzedniej noty o CXFie, którą napisałem jakiś czas temu, gonię aby uzupełnić brak konfiguracji klienta. Sam proces jest bardzo zbliżony do tworzenia klienta w oparciu o XFire. Nie jest wymagana duża ilość kodu Javy, a w zasadzie tylko dwa pliki XML (client.xml, myservice.xml).
Pierwszy z nich odpowiada za wczytanie wymaganych rozszerzeń CXFa oraz definicję bazowej konfiguracji fabryki z interceptorami. W interceptorach możemy skonfigurować logowanie, obsługę załączników czy standardów WS-Security etc. Wszystkie te ustawienia będą dziedziczone, a fabryki docelowych usług będą dodawać tylko adres, do odpytywania. Na koniec bean klienta będzie miał określony autowire by nie przekazywać mu wszystkich własności.
Read the rest of this entry »
Od jakiegoś czasu w pracy do tworzenia usług sieciowych korzystam z Apache CXF. Jako że biblioteka jest stosunkowo nowa i nie najlepiej udokumentowana postanowiłem przedstawić na blogu jak wygląda proces tworzenia.
CXF jest połączeniem kilku bibliotek – YOKO, Celtixa oraz XFire. Każda z nich wcześniej realizowała pewien fragment obecnej funkcjonalności CXF – YOKO obsługuje Corbę a XFire usługi sieciowe. Obecne CXF jest gotowy do używania “produkcyjnego”, ponieważ niedawno wyszedł z fazy inkubacji. 🙂
Read the rest of this entry »
Jakiś czas temu, jeszcze podczas pracy w poprzedniej firmie przypadło mi zadanie podpięcia się pod magistralę usług opartą o Apache Service Mix (SMX). Był to wówczas dla mnie temat zupełnie nowy, ba nawet nie wiedziałem z czym to się je. 🙂 Koniec końców jednak podpięcie pod ESB (Enterprises Service Bus) nie było w ogóle trudne. Po jakimś czasie i drobnych przetasowaniach na płaszczyźnie zawodowej zająłem się SMX-em nie jako klient magistrali a osoba implementująca usługi na szynie a ten wpis jest drobną przeróbką prezentacji, którą przygotowałem w pracy.
Read the rest of this entry »
Recent comments