niedziela, 30 grudnia 2007

Kreatory w GWT

W dystrybucji GWT znajdują się cztery skrypty cmd, które w największym skrócie można nazwać kreatorami. Każdy z nich jest wykorzystywany na różnym etapie tworzenia aplikacji.

projectCreator
GWT pozwala na łatwą integrację ze środowiskiem Eclipse, dlatego też jeżeli podczas tworzenia aplikacji programista zamierza korzystać z tego IDE, wówczas powinien użyć tego narzędzia. Kreator ten zakłada strukturę katalogów (wraz z plikami .project oraz .classpath) , która pozwoli łatwo zaimportować tworzoną aplikację jako projekt Eclipse.

Wykonując komendę: Utworzona zostanie następująca struktura: applicationCreator
Kreator ten pełni trzy funkcje:

  • Wytwarza strukturę pakietów dla aplikacji.
  • Generuje domyślne pliki HTML i Java spięte w prostym pliku module XML. Te pliki stanowią prostą aplikację od której można zacząć budowanie bardziej zaawansowanych funkcjonalności.
  • Tworzy skrypty cmd, które pozwalają przekompilować i uruchomić aplikację w trybie hosted mode.
Wykonując komendę (bez Eclipse): Wykonując komendę (z Eclipse): Utworzona zostanie następująca struktura: W przypadku parametru -eclipse dodatkowo powstanie: i18nCreator
Jeżeli pojawia się skrót i18n to oczywiście chodzi o internacjonalizację. Tym kreatorem wytwarzamy proste pliki properties zawierające teksty stałe w formie klucz/wartość. Generowany jest również skrypt cmd [Appl]-i18n, który na podstawie plików properties generuje interfejs Java poprzez który mamy dostęp do tekstów stałych z kodu Java aplikacji GWT.

Wykonując komendę (bez Eclipse): Wykonując komendę (z Eclipse): Utworzona zostanie następująca struktura: W przypadku parametru -eclipse dodatkowo powstanie: jUnitCreator
Tworzy odpowiedni katalog oraz pliki, w którym należy umieścić testy jednostkowe aplikacji GWT.

Wykonując komendę (bez Eclipse): Wykonując komendę (z Eclipse): Utworzona zostanie następująca struktura: W przypadku parametru -eclipse dodatkowo powstanie: Dzięki kreatorom można w ciągu dosłownie kilku chwil zbudować swoją pierwsza aplikację w GWT, dzięki czemu nawet niecierpliwi się nie zniechęcą. Oczywiście bardziej istotne jest to, że nie trzeba wykonywać powtarzalnych czynności, które może za nas wykonać automat.

niedziela, 23 grudnia 2007

Dlaczego GWT jest lepsze od Echo2

Pamiętam jak dawno dawno temu natrafiłem na bardzo ciekawy framework jakim był Echo2, sama koncepcja pisania dla mnie była genialna, ale jednak po dokładniejszej analizie tego rozwiązania stwierdziłem, iż w praktyce ma ona małe szanse powodzenia. Teraz nadeszedł moment, gdy postanowiłem porównać go z GWT, ponieważ sama idea pisania aplikacji w tych frameworkach jest analogiczna, ale zasada działania już zupełnie inna.

Zarówno w GWT jak i w Echo2 programista używa API zbliżonego do Swinga (lub jak kto woli do AWT). Poniżej zamieszony został przykład jak dodać pole edycyjne i przycisk w Echo2: Natomiast w GWT ten sam przykład wygląda tak: Jeżeli chodzi o porównanie kodu nie ma zasadniczych różnic, natomiast w działaniu sytuacja jest odmienna.

GWT na podstawie kodu Java generuje JavaScript, który jest uruchamiany w przeglądarce Internetowej, natomiast Echo2 kompiluje kod do klasy Java, a następnie uruchamia go na serwerze. To powoduje, iż każde zdarzenie (np. naciśnięcie przycisku) generuje ruch pomiędzy przeglądarką Internetową, a serwerem. Wybraźmy sobie co by było gdyby po każdym wyjściu z pola edycyjnego było uruchamiane zdarzenie (Echo2 ograniczyło na szczęście uruchamianie takich zdarzeń). Stąd podejście proponowane przez Echo2 zupełnie do mnie nie przemawia, bo generuje zbyt duży ruch w sieci. Oczywiście są pewne zalety takiego podejścia np. na serwerze wiadomo jaki jest stan aplikacji, jest wysyłany tylko niezbędny JavaScript.

Twórcy GWT wybrali wg mnie bardziej naturalną drogę skoro interfejs jest w przeglądarce to i aplikacja jest w niej uruchamiana, a komunikuje się z serwerem tylko wtedy gdy jest to niezbędne.

niedziela, 11 listopada 2007

Html Hack dobry na wszystko

Pamiętam czasy gdy programy pisało się korzystając z biblioteki curses, a interfejs użytkownika stanowił terminal 80x24. Nie będę się na ten temat zbytnio rozwodził, ale wspominam jedną rzecz jak coś napisałem to działało na każdym terminalu. Później przyszła era aplikacji GUI (np. Delphi, Swing), aż wreszcie doszliśmy do przeglądarek Internetowych i tutaj zaczeły się problemy. Na Firefoxie coś działa, a na Internet Explorze nie itd. W poprzednim tygodniu natrafiłem właśnie na taki problem i jak zawsze z pomocą przyszedł "html hack", czyli wykorzystanie słynnej funkcji JavaScript setTimeout.

Zacznę od początku (tak chyba najlepiej) czyli od przykładu, który zobrazuje problem na który natrafiłem. Otóż chodziło o to aby przycisk po zaznaczeniu checkboxa się pokazywał (dodatkowo atrybut position musiał być relative), a po odznaczeniu chował (dodatkowo atrybut position musiał być absolute). Cały kod html zawarłem poniżej: Po uruchomieniu tego przykładu okazało się, że owszem w Firefoxie działa wszystko jak należy, ale w Internet Explorerze przycisk jest niewidoczny, przy czym jest rezerwowane na niego miejsce.

Oczywiście pełen pokory, ale i wiary w sukces zabrałem się do pracy, już po kilku chwilach stwierdziłem, że problem jest związany z przypisywaniem do atrybutu position wartości relative. Niestety Internet Explorer z tym sobie nie radzi. Problem znaleziony, więc przeszedłem do rozwiązania, które sprowadziło się do pragmatycznego posunięcia jakim było zastosowanie funkcji setTimeout - popularnego i "lubianego" html hacku.

Poniżej zamieszczam zmodyfikowany kod, który działa w Internet Explorerze: Zachęcam Was do podzielania się swoimi ciekawymi doświadczeniami.

sobota, 3 listopada 2007

Spotkaj swojego idola - James Gosling

Chyba nikomu nie trzeba przybliżać osoby Jamesa Goslinga. Ze względu na weekend zamieszczam link do krótkiego filmu, którego jest on głównym bohaterem. Przyznam, że film mnie bardzo rozbawił: There are better ways to meet your idols

piątek, 26 października 2007

GWT - module czy entry-point

W programowaniu często jest tak, że zrobienie podstawowej rzeczy jest proste i szybkie, dotyczy to w szczególności frameworków. W dystrybucji danej biblioteki mamy często mnóstwo przykładów, które charakteryzują się jednym elementem - są proste, niekiedy zbyt proste. Podobnie zresztą jest z większością tutoriali. Jednak czy jest to problem. Na początku nie, ale później owszem. Bo co z tego, że po zapoznaniu się z przykładami, czy kursami potrafimy zrobić jeden formularz skoro nie wiemy jak zaprojektować, a później zaprogramować całą aplikację. Oczywiście intuicja podpowiada programiście, w którym kierunku należy podążać, jednak zawsze zadaje sobie on pytanie czy jest to kierunek słuszny, zgodny ze sztuką i czy architektura jego aplikacji jest optymalna.

Właśnie na taki problem napotkałem tworząc aplikację w GWT. Moja aplikacja składać się miała z dwóch elementów: panelu dla użytkownika oraz panelu dla administratora. Jednak pewne elementy tych paneli miały być wspólne: zarówno elementy ekranu jak np. DialogBox, jak również serwisy RPC. Więc oto stanąłem przed dylematem, jak to rozwiązać w GWT - czy stworzyć jeden moduł z kilkoma elementami entry-point, czy kilka modułów. Na początku byłem skłonny tworzyć kilka entry-pointów, do czasu gdy uprzytomniłem sobie, iż moduły mogą po sobie dziedziczyć. Wówczas było już z górki, postanowiłem stowrzyć jeden moduł ogólny, w którym umieściłem wspólny kod dla obu paneli, oraz dwa moduły zawierające specyficzny kod, jeden dla panelu administratora, a drugi dla panelu użytkownika. Oczywiście te dwa moduły dziedziczyły po module ogólnym. Wszystko było w obrębie jednego projektu Eclipse.

Teraz przedstawie to od strony technicznej.
W pierwszej kolejności tworzymy moduł ogólny, który będzie wyglądał następująco:

Pakiety: Zawartość pakietów: Zawartość pliku Common.gwt.xml: Należy zwrócić uwage na to, iż ten moduł nie zawiera żadnego elementu entry-point, ponieważ będzie on przechowywał wszystkie elementy wspólne, a sam nie będzie uruchamiany, stąd też pakiet com.blogspot.coderlife.app.common.public jest pusty nie zawiera żadnej strony html.

W drugim kroku tworzymy moduł administratora, który będzie wyglądał następująco:

Pakiety: Zawartość pakietów: Zawartość pliku AdminPanel.gwt.xml: Ten moduł już będzie uruchamiany poprzez plik AdminPanel.html stąd zawiera on entry-point. Najbardziej istotne jest dziedziczenie tutaj po module Common.

Nie będę zamieszczał zawartości UserPanel ponieważ jest analogiczna do AdminPanel.

Reasumując wg mnie jeżeli aplikacja ma dwa niezależne panele (ekrany) powinno stworzyć się dwa moduły dla każdego z nich, natomiast wspólne elementy umieścić w trzecim wspólnym module (nie zawierającym żadnego entry-pointa).

Zachęcam Was do podzielenia się opiniami co do prawidłowego modelu tworzenia aplikacji w GWT.

sobota, 20 października 2007

Parsowanie XML przekazanego przez sockety

Zacznę od przedstawienia problemu, który oczywiście nie istnieje dopóki się go nie napotka :) Problem tkwi w tym, iż część parserów XML zamyka wejściowy strumień (InputStream) kiedy napotka EOF (-1). Dotyczy to choćby Xercesa, który jest domyślnym parserem dla biblioteki JDOM. Oczywiście nie byłoby w tym nic złego gdyby wejściowym strumieniem nie był SocketInputStream, ponieważ jego zamknięcie powoduje jeden niekoniecznie pożądany skutek, a mianowicie zamknięcie socketu, który w efekcie jest już bezużyteczny co oznacza nic innego jak to, iż nie można przez niego wysłać odpowiedzi.

W przypadku dużej części aplikacji sockety są wykorzystywane do realizacji klasycznego modelu żądanie-odpowiedź np. klient wysyła do serwera dokument XML, serwer go przetwarza, a następnie odpowiada klientowi innym dokumentem XML. Jednak w przypadku gdy po wczytaniu dokumentu XML przez serwer socket zostanie zamknięty, klientowi nie zostanie udzielona odpowiedź.

Co można w takim razie zrobić aby osiągnąć pożądany efekt? Rozwiązania są dwa przy czym drugie z nich można zrealizować na kilka sposobów. Pierwsze rozwiązanie to opakowanie InputStream (z socketu) w taki sposób aby nie zamykał on połączenia, czyli przesłonięcie metody close(). Drugie rozwiązanie to przeczytanie wszystkiego do bufora, a następnie przekazanie jego zawartości do parsera XML. Przy czym co zrobić jeżeli wejściowy strumień danych jest duży i nie chcemy niepotrzebnie czekać aż zostanie cały wczytany i dopiero wówczas przekażemy go do parsera. Przecież przychodzące bajty mogą być przetwarzane przez parser XML zanim przyjdą kolejne.

Jak to zrobić w takim razie efektywnie: Zestawiamy ze sobą dwa strumienie typu piped: Tworzymy wątek łączący strumień wyjściowy piped ze strumieniem wejściowym socketu. Jego zadaniem jest czytanie danych z clientSocketInputStream do pipedOutputStream, który jest połączony z pipedInputStream, który możemy bezpośrednio przekazać do parsera XML: Implementacji klasy Output2InputThread nie będę zamieszczał w całości, natomiast zamieszczę fragmenty, które pozwolą zorientować się co powinno się w niej znaleźć: Nie zamieściłem kodu, który sprawdzi kiedy należy przestać czytać, ale takie coś już każdy może zrealizować samodzielnie. Wcześniej oczywiście trzeba ustalić sposób informowania o zakończeniu przesyłania dokumentu XML, można to zrobić np. poprzez przesłanie przed dokumentem nagłówka z ilością bajtów, które należy wczytać lub na końcu dokumentu jakiegoś umownego znacznika. Zwracam też uwagę, że ustalenie rozmiaru bufora na określoną wartość wcale nie oznacza, że podaczas jednej iteracji zostanie on cały zapełniony, w szczególnym przypadku może zostać wczytany tylko jeden bajt.

Zachęcam Was do podzielenia się swoimi sposobami na rozwiązanie przedstawionego przeze mnie problemu.

czwartek, 18 października 2007

GWT WYSIWYG powrót do korzeni

Komu się nie zdarzyło czegoś skrobnąć w Swingu i/lub Delphi z wykorzystaniem graficznego designera, pewnie większości programistów. Owszem może kod który powstaje dzięki takiemu narzędziu nie jest najwyższych lotów, ale przynajmniej taki interfejs graficzny tworzy się po prostu szybko, nawet nie będąc ekspertem w zakresie danej biblioteki, koncentrujemy się tylko nad obsługą poszczególnych zdarzeń (np. onClick itd). No tak ale co z tego jak dzisiaj każdy (no może prawie każdy) oczekuje, że aplikacja będzie dostępna przez przeglądarkę Internetową i oczywiście aplety odpadają bo trzeba instalować JRE itd.

Pamiętam historię, którą opowiedział mi mój znajomy o firmie w której programiści kilka lat temu tworzyli aplikację w Visual Basicu, a teraz robią to w JSP. Zapytałem czy są zadowoleni, a on odpowiedział, że nie do końca, ponieważ nie potrafią zrozumieć dlaczego, coś co tworzyli przez jeden dzień zajmuje im teraz trzy dni... Ta krótka opowieść zalatuję nostalgią za korzeniami, za środowiskami designerskimi typu WYSIWYG, w których interfejs użytkownika wyklikujemy, a oprogramowujemy tylko zdarzenia. Czy aby MVC było tym na co czekali programiści z opowieści... otóż nie.

Czekali na GWT Designera narzędzie, które pozwala programować w taki sposób jakbyśmy to robili w Swingu, różnica jest tylko jedna efektem naszego klikania jest interfejs webowy.

GWT Designer to kreator GUI, który wspiera również GWT. Posiada on zarówno możliwość wizualnego tworzenia interfejsu (WYSIWYG) jak i zestaw kreatorów, które generują za nas kod Java. Żeby stworzyć sam interfejs żytkownika nie trzeba pisać nawet jednej linijki kodu, tylko oprogramować zdarzenia. Chociaż jeżeli mamy ochotę wówczas oczywiście taki kod możemy sami zedytować, po czym ponownie przełączyć się do trybu wizualizacji. Wręcz w fantastyczny sposób jest wsparta internacjonalizacja - bez kompilacji po wyborze z listy rozwijanej języka możemy kontrolować jak będzie wyglądał nasz interfejs w różnych lokalizacjach.

Korzystając z WYSWIG możemy:
  • dodawać kontrolki techniką drag&drop,
  • dodawać obsługę zdarzeń poprzez kliknięcie w kontrolkę,
  • zmieniać właściwości kontrolki poprzez użycie palety edytora właściwości,
  • zmieniać i wykonywać refactoring wygenerowanego kodu, efekty natychmiast są widoczne w edytorze wizualnym,
  • narzędzi radzi sobie również z kodem, który został napisany ręcznie, potrafi go przeanalizować i zaprezentować w wizualnym narzędziu,
  • a co najważniejsze sam GWT Designer jest niczym innym jak pluginem do Eclipse,
  • największą jego wadą jest to że nie jest darmowy.

Najszybciej możecie zapoznać się z jego możliwościami poprzez filmiki demo dostępne pod adresem: http://www.instantiations.com/gwtdesigner/demos.html

Źródło: http://www.instantiations.com/gwtdesigner/index.html

środa, 17 października 2007

YUI rywal GWT?

Google udostępniło programistom Google Web Toolkit (GWT), framework do szybkiego i przyjemnego tworzenia aplikacji webowych. Oczywiście słowo "przyjemnego" jest kwestią względną, ale na pewno tak mógłby powiedzieć programista Java, który stroni od JavaScriptu i HTMLa. Dlaczego? Bo w GWT nie musi stosować żadnego innego języka poza Javą. Ale czy to jest właśnie kierunek rozwoju frameworków webowych, który okaże się tym najwłaściwszym. W tym momencie ciężko przesądzić.

Zupełnie inną koncepcję proponuje Yahoo - tak, tak Yahoo też postanowiło wystawić swojego zawodnika :) Nazywa się on The Yahoo! User Interface (YUI). Biblioteka ta jest zbiorem narzędzi i kontrolek napisanych w JavaScripcie, do budowania interaktywnych aplikacji webowych. Opiera się w dużej mierze na operowaniu na DOMie, DHTMLu i AJAXie. Wszytkie komponenty dostarczane przez Yahoo są open sourcowe na licencji BSD i można ich używać do woli.

W celu zaprezentowania podstawowych możliwości Yahoo posłuże się prostym przykładem komponentu AutoComplete.

Aby w ogóle użyc kontrolki musimy załączyć do naszej strony HTML pliki CSS i JavaScript: Następnie tworzymy instancję pola AutoComplete w następujący sposób: Konstruktor AutoComplete zawiera trzy parametry:

  • Identyfikator pola typu texbox lub textarea w które użytkownik będzie wpisywał zapytanie.

  • Identyfikator elementu HTML który będzie kontenerem zawierającym wyniki zapytania.

  • Wreszcie trzeci parametr to DataSource, który będzie zawierał dane które będą zawężane przez zapytanie i prezentowane w kontenerze.

Zanim zostanie powołany obiekt AutoComplete, należy zainicjować trzeci parametr DataSource można to zrobić na trzy różne sposby w zależności od potrzeb.

Prosta tablica po stronie przeglądarki: Funkcja JavaScript, która dostarczy dane: Wreszcie najbardziej przydatny sposób pociągnięcie danych z serwera: Mam nadzieję, że przykład ten przybliżył zasadę działania YUI. Więcej informacji znajdziecie na stronie:
http://developer.yahoo.com/yui/

Zachęcam również do dyskusji do jakich frameworków webowych należy przyszłość?

sobota, 13 października 2007

Drag&Drop w GWT

Od czasu kiedy pojawiło się GWT minęło już sporo czasu, dlatego można go już oceniać nie tylko pod kątem tego czy zaproponowana przez Google koncepcja jest właśnie tą na którą czekają programiści webowi, którym dzierganie w JavaScriptcie po prostu nie odpowiada, ale również można oceniać go pod kątem popularności jaką zdobywa i przyznam, że przeglądając zasoby Internetu wyraźnie widać, że pozostawia konkurencję w tyle jak choćby framework YUI tworzony przez Yahoo.

Innym istotnym elementem, który wpływa w zasadniczy sposób na popularność danego frameworku jest wsparcie jakie zyskuje on w środowisku OpenSource'owym, głównie mam tutaj na myśli ilość darmowych rozszerzeń jaka jest tworzona przez to grono programistów.
Wczoraj przeszukując Internet natrafiłem na bardzo ciekawą bibliotekę gwt-dnd, która przy naprawdę niewielkim nakładzie pracy pozwoli na zbudowanie interfejsu użytkownika z elementami Drag&Drop.

Podstawową zaletą tej biblioteki jest to, iż możemy korzystać ze standarowych widgetów i paneli dostarczanych przez GWT - nie muszą one implementować specjalnych klas lub interfejsów, po prostu wystarczy użyć istniejące widgety i panele. Nie będę się koncentrował w dalszym opisie nad tym jakie funkcjonalności dostarcza ta biblioteka, natomiast zaprezentuję fragment kodu, który zaprezentuje prostotę użycia tego rozszerzenia.

W pierwszym kroku tworzymy główny panel poza który nie będą mogły wyjść przeciagane elementy: Następnie wewnątrz tego panelu tworzymy kolejny panel tym razem będzie on określał obszar poza którym nie będzie można upuścić widgetu (w naszym przypadku będzie to prostu label): Kolejny krok to stworzenie tzw. DragControllera, w którym umieszczamy panel poza który nie będzie można przeciągać widgetów (co nie znaczy, że będzie można w nim go upuszczać): Teraz dodajemy analogicznie tzw. DropController, w którym umieszczamy panel w obrębie którego mogą zostać upuszczone widgety: Rejestrujemy DropController w DragControllerze: Tworzymy etykiete, którą będziemy przeciągać i upuszczać w obrębie targetPanel: Za pośrednictwem DragControllera robimy z etykiety widget, który można przeciągać: Siła tej biblioteki tkwi w prostocie jej użycia, w 12 liniach kodu można zrobić naprawdę dużo zamieszania :)

Źródła z których korzystałem i wszystkim polecam się z nimi zapoznać:
http://code.google.com/p/gwt-dnd/
http://code.google.com/p/gwt-dnd/wiki/GettingStarted

Dla zainteresowanych zamieszczam kody źródłowe.

Kod źródłowy pliku MyApplication.gwt.xml: Kod źródłowy pliku MyApplication.java:

Portlety w Sun Java Studio Creator 2

Ostatnio zainteresowałem się nieco poważniej tematyką portali - po zapoznaniu się z kilkoma darmowymi rozwiązaniami zdecydowałem, że w dalszej wędrówce będę korzystał z Liferaya ze względu na jego stabilność, dojrzałość i duże możliwości oraz zgodność z JSR 168.

Ze względu na to, iż jestem programistą głównie moją uwagę skupiłem na pisaniu portletów, a że JSP i Servlety są bardzo bliskie mej duszy, pisanie ich nie stanowiło dla mnie najmniejszego problemu - okazało się zajęciem miłym, łatwym i przyjemnym, do czasu...

Właśnie do czasu kiedy uznałem, że warto by skorzystać z jakiegoś frameworku (nawet więcej - środowiska deweloperskiego), jednak takiego w którym byłoby dużo komponentów na dość wysokim poziomie abstrakcji, graficzne środowisko deweloperskie do projektowania stron WWW np. tak jak w Sun Java Studio Creator 2. (Przypomnę, że narzędzie to posiada graficzny edytor do budowania stron JSF.)

Zanim do tego przystąpiłem zapoznałem sie nieco dokładniej ze specyfikacją JSR 168. Szczególnie zainteresował mnie rozdział CSS Style Definitions, zawarte są w nim wszystkie standardowe style CSS, które powinny być używane w portletach. Dlaczego powinny być? Otóż dlatego aby każdy portlet wyglądał tak samo pod kątem kolorystyki i stylistyki, którą narzuca wybrany przez użytkownika temat dostępny w konfiguracji portalu. Bo jakże okrutną torturą byłoby dla obiorcy gdyby zobaczył kilka różnych portletów na jednej stronie w zupełnie innej kolorystyce, które nijak nie przystają do całości, a przecież o tą spójność chodzi.

Postanowiłem sprawdzić jak to jest w praktyce i napisałem trochę kodu w JSF (korzystając ze standardowej implementacji MyFaces zgodnej z JSF 1.2). Dlaczego akurat wybrałem JSF, ponieważ już zdążyłem się zorientować, iż jest to technologia najbardziej odpowiednia jeżeli chodzi o pisanie portletów - tak wynika z opinii krążących w Internecie.

Poniżej zamieszczam przykład w JSF napisany zgodnie z rozdziałem CSS Style Definitions: Nietrudno zauważyć, że programista w powyższym kodzie skoncentrował się na tym aby używać standardowych stylów CSS ze specyfikacji JSR 168. I właśnie do tej pory było pięknie, niemal sielankowo... Aż nastąpił czas na próbę generalną Sun Java Studio Creator 2, środowiska deweloperskiego, które pozwala programiście w kilka minut (no może godzin) niemal wyklikać całą aplikację - co można zobaczyć na prezentacji Java Studio Creator 2 in Action. (Wspomnę tylko, że takie prezentacje na menadżerach robią ogromne wrażenie i nie zawsze jest im łatwo wytłumaczyć, że takie rozwiązanie posiada też pewne wady i koniecznie idealnie pasuje do realiów firmy).

Stworzyłem stronę JSF, która wykorzystywała kilka dostępnych komponentów: tabelkę, przycisk itd. Ze względu, że Sun generuje dla własnych komponetów swoje style CSS, postanowiłem w jednym z przycisków je przedefiniować na styl zgodny ze specyfikacją JSR 168: Jakież było moje zdziwienie, gdy po uruchomieniu portletu powyższa zmiana nie przyniosła skutku. W akcie desperacji zajrzałem do źródła wygenerowanej strony HTML w przeglądarce WWW. Oto efekty: Co się okazało komponent wygenerował moją klasę CSS portlet-form-button, ale wcześniej wstawił swoją btn2 - niestandardową, niezgodną z definicją styli CSS dla portali, a że w klasie btn2 było zdefinowane mnóstwo atrybutów CSS to moja biedna klasa portlet-form-button niewiel mogła tu przedefinować. Było źle, ale czy może być jeszcze gorzej, okazuje się, że tak. Otóż zaczałem szukać gdzie się podział plik ze stylami CSS, w których znajduję się nieszczęsna definicja btn2, bo może by dało się go zwariantować osobno dla każdego tematu portalu. Wprowadziłbym oddzielny plik z odrębną definicją styli CSS i umieścił w każdym temacie. Po pewnym czasie znalazł się nieszczęśnik w jednej z bilbiliotek SUNa spakowanej do jara. Jak to działa: w momencie gdy ładowany jest portlet ta biblioteka jest dynamicznie z takiego jara wyciągana i do niego dołączana. Efekt jest taki, że każdy portlet ma swoją definicję styli CSS, co nie do końca przystaje do standardu JSR 168.

Występują też inne problemy związane z tym co napisałem powyżej. Jeżeli będziemy chcieli uruchomić dwa portlety napisane właśnie w środowisku deweloperskim SUN od dwóch niezależnych dostawców, z których każdy zastosował inne style CSS np. blue.css i gray.css. To wówczas obydwa portlety przyjmią style od portletu, który uruchomi się ostatni - czyli mamy do czynienia z swego rodzaju loterią, bo to użytkownik może decydować o kolejnośći ich występowania (rozmieszczanie portletów na stronie).
Problem ten można rozwiązać poprzez zastosowanie pewnego obejścia zaproponowanego na blogu pracownika Suna Conflicting Creator Themes in Portlets. Proponuje on dołączenie kolejny raz stylu CSS w stopce, czyli przy dwóch portletach będziemy mieć trzy definicje stylów oraz definicje standardowe dla danego portalu.

Wszystko podsumuję starym przysłowiem: Nie wszystko złoto co się świeci - mimo, że środowisko deweloperskie Sun Java Studio Creator 2 na pierwszy rzut oka oferuję naprawdę dużo, to poważne błędy konstrukcyjne dyskwalifikują je z użycia przy budowaniu portletów.

W czym taki razie pisać portlety skoro standardowa implementacja JSF 1.2 okaże się niewystarczająca, bo oczekiwania są większe (np. tabelki ze stronicowaniem, sortowaniem itd.) może użycie komponentów Tomahawk w połączeniu z ajax4jsf? Niektóry firmy właśnie na takie połączenie stawiają Interview with Max Katz.

Zachęcam do dyskusji W czym pisać portlety (JSR-168) w sposób efektywny, ale i zgodny ze sztuką?