Wygodne środowisko dla programisty z JRebel

jrebel_biggerOd dłuższego czasu pracuję z następującymi narzędziami: Maven, Eclipse, Jetty. Nigdy nie starałem się na to by moje projekty dobrze współgrały z Eclipse ponieważ wszystko i tak uruchamiam przez Mavena. Korzyścią jest przenośność tego rozwiązania, wadą brak klikalnej wygody, tj zakładki serwerów w Eclipse i aplikacji które są na nich uruchomione.
more

Latest comments across all posts

Najnowsze wpisy

post Spring 3.0 RC3 + Maven

Właśnie wyłapałem na Twitterze, że Spring 3.0 RC3 został wydany.

Dla tych, którzy chcieli by pobrać nową wersję do swojego projektu opartego o Mavena drobna informacja – repozytorium z tymi artefaktami znajduje się pod adresem http://maven.springframework.org/milestone. Miejmy nadzieję, że będzie to repozytorium które się nie zmieni po 3 miesiącach na inne.

W razie problemów – można zawsze skorzystać z repozytorium utrzymywanego na serwerze Code-House.


post GWT oraz implementacje MVC

GWT, czyli Google Web Toolkit to nic innego jak zbiór komponentów, które można użyć podczas tworzenia aplikacji. GWT jest łatwe, kod tworzy się szybko i łatwo uruchamia chociażby z poziomu Mavena, jednakże największym problemem nie jest to jak stworzyć okienko, ale jak zorganizować projekt. W tym poście postaram się przedstawić kilka gotowych bibliotek, z którymi się zetknąłem podczas swych bojów z budowaniem sporej aplikacji.


Ilość implementacji MVC dla GWT jest dosyć duża a temat był poruszany na zagranicznych blogach już nie jeden raz, wystarczy zajrzeć na poniższe strony:

  • W marcu 2009 Matt Raible opisał swoje problemy z komponentami GXT oraz problematycznym MVC stworzonym przez autorów tejże biblioteki
  • W kwietniu 2009 pojawiło się pierwsze zestawienie implementacji MVC na blogu Supply Chain Technology
  • W maju 2009 na tym samym blogu pojawiła się aktualizacja z nowymi pozycjami.
  • Również w maju 2009 odbyła się konferencja Google IO na której temat developmentu GWT był szeroko i dokładnie omówiony.

Zacząłem nieśmiało, bo od stworzenia “szyny” którą mogły by się komunikować różne komponenty. Miała ona na celu zmniejszenie ilości bezpośrednich powiązań między elementami aplikacji. Pomogło, ale to nie było jeszcze to, co uporządkowało aplikację.

Drugie podejście mimo obaw wyniesionych z pierwszego linku padło na lightweight MVC z biblioteki GXT. Udało mi się stworzyć działającą aplikację, jednakże brak jasnego podziału co, kto i jak ma robić strasznie mi doskwierał. Problematyczna okazała się również próba stworzenia hierarchii kontrolerów, a zrobienie aplikacji od zera sprowadzało się tak na prawdę do skopiowania i przerobienia przykładu z Mail App. Podobnie jak Matt nigdy też nie wyłapałem różnicy między metodami Dispatcher.dispatch() oraz Dispatcher.forwardEvent().

Trzecie podejście do MVC zakrawało już szaleństwem. Po przejrzeniu dokumentacji GWTruts stwierdziłem, że zapowiada się ciekawie. Odseparowany widok i kontroler, API przypominające nieco Spring MVC, nieco XML do okraszenia całości wstrzykiwaniem zależności. Wszystko to jednak na nic, gdyż całość opiera się na mapowaniu adresów z przeglądarki do kontrolerów. Krzywe koniec końców okazało się też przekazywanie map z argumentami i w dalszym ciągu brak jakichkolwiek idei na zorganizowanie wszystkiego. A zapomniałbym – jeśli chcecie walidacji to musicie pogodzić się z tym że 1 kontroler to 1 klasa do sprawdzania danych. Szkoda że tego nie można “wstrzyknąć”.

Dobra, skoro nie GWTruts, nie GXT, i nie Event Bus to co? Krótki przegląd GWT-MVC skończył się odrzuceniem szkieletu. Skąd niby kontroler ma zajmować się tym gdzie ma wylądować widok? A tak właśnie się dzieje w tym szkielecie ponieważ kontroler wywołuje DOMPlacera by gdzieś umieścić widok. Jak by tych fanaberii było mało doszedł jeszcze interfejs Maskable który ma przykrywać elementy w trakcie renderowania. Dodajmy do tego przykłady które się sprowadzały do przycisków +2, -2 i inputa. Pytanie – co to ma do klasycznego MVC?

Tym oto sposobem dotarłem do ostatniego projektu, który mi zaimponował rozmiarem dokumentacji, spójną koncepcją i masą ograniczeń – Pure MVC. Projekt, który pierwotnie miał sporo do czynienia z Flashem, a który dzięki swojemu porządkowi został przepisany również na inne języki – min. PHP, Javę. Wśród portów nie zabrakło również wersji dla GWT. Nie muszę pisać jak bardzo mnie to ucieszyło, prawda? :-)
Całkiem duży przykład obrazuje powiązania pomiędzy komponentami oraz to jak powinny się komunikować:
Employee Admin Demo

Uzbrojony w ten zakres informacji stworzyłem pierwszą przykładową aplikację z ekranem logowania oraz jedną tabelką. Stopniowo go rozbudowując dotarłem do momentu w którym moja aplikacja w końcu przestała się kręcić wokół tego “które MVC” wybrać i zaczęła nabierać funkcjonalności biznesowej. Po długich bojach i masie straconego czasu, odradzam wszystkie inne implementacje Model View Controller dla GWT. Pure MVC jest po prostu najlepsze. :-)


post Instalowanie oprogramowania Atlassian cz. 1

Kilka dni temu trafiłem na informacje o tym, że firma Atlassian uruchomiła “promocję” w której wyprzedaje licencje startowe na swoje produkty za 10$. Tym oto sposobem za równowartość dobrego obuwia (niecałe 175 zł) wszedłem w posiadanie sześciu licencji na Crowd, Jira, GreenHopper, Confluence, Fisheye i Bamboo. W poście tym krótki opis instalacji na Tomcat 6.x pierwszych czterech.

Przygotowania

Uprzedzam, że instrukcja jest pisana z pamięci więc mogą pojawić się jakieś braki. W przypadku gdy instrukcja nie zadziała proszę o komentarz, a postaram się pomóc i uzupełnić wpis tak by był kompletny.
Aby ułatwić sobie życie i zaoszczędzić pamięć na serwerze wszystkie produkty będzie obsługiwała jedna instancja Tomcat i PostgreSQL. Niestety Fisheye i Bamboo są dostępne tylko w wersji standalone, stąd proces ich instalacji będzie nieco inny. Zanim ruszymy z całością pobieramy od producenta oprogramowanie.
Pobieranie Crowd
Przeskakujemy na zakładkę Linux i następnie klikamy w prawym górnym rogu i pobieramy wersję standalone. Wykonujemy polecenie

tar -xvzf atlassian-crowd-2.0.2.tar.gz

Po rozpakowaniu pojawią się następujące katalogi

  • apache-tomcat
  • client
  • crowd-openidclient-webapp
  • crowd-openidserver-webapp
  • crowd-webapp
  • demo-src
  • demo-webapp
  • etc

Będziemy potrzebować tylko dwóch – crowd-webapp oraz opcjonalnie openidserver. Dystrybucja standalone zawiera już Tomcata, zatem najpotrzebniejsze biblioteki weźmiemy już stąd. :) Kopiujemy biblioteki:

  • activation-1.1.jar
  • mail-1.4.jar
  • jta-1.0.1B.jar

Do katalogu lib naszego tomcata. Na Gentoo jest to /usr/share/tomcat-6/lib.
Pierwsze dwie biblioteki będą potrzebne do używania obiektu javax.mail.Session zapisanego w drzewie JNDI. Dodatkowo pobieramy driver JDBC dla bazy PostgreSQL. Należy pamiętać że wersja JDBC 4 jest przeznaczona do uruchamiania na Java 1.6. Ja ściągnąłem wersję 8.4-701.jdbc4. Mając te biblioteki przystępujemy do konfiguracji kontekstu Tomcata.
W pierwszym kroku dodajemy globalną sesję mailową którą będziemy współdzielić między aplikacjami. W ten sposób zmiana w jednym miejscu będzie skutkować “aktualizacją” konfiguracji wszystkich aplikacji. Edytujemy plik $TOMCAT_HOME/conf/server.xml. W sekcji GlobalNaminResources umieszczamy dodatkowy fragment:

  <GlobalNamingResources>
    <!-- Ten wpis jest domyślnie dostępny -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />

    <Resource name="mail/Session" auth="Container"
              type="javax.mail.Session"
              description="JavaMail Session"
              username="user"
              password="pass"
              mail.smtp.host="host"
              mail.smtp.auth="true"
              mail.user="user"
              mail.password="pass"
              mail.transport.protocol="smtp"
              />
  </GlobalNamingResources>

Konieczna będzie również zmiana sekcji Server:

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8" /><!-- dodajemy URIEncoding -->

Atrybut URIEncoding będzie wymagany przez min. confluence i umożliwia przesyłanie krzaczków w adresie. Warto również zwiększyć limity pamięci Tomcata ponieważ na domyślnych długo nie pociągnie i prawdopodobnie już przy instalacji JIRA albo Confluence poleci OutOfMemory.

Drugi krok to ustawienie zmiennej crowd-home. W tym celu należy wyedytować plik crowd-webapp/WEB-INF/classes/crowd-init.properties.

crowd.home=/var/lib/tomcat-6/atlassian/crowd-home

W razie problemów można “zresetować” instalację usuwając folder home, czego oczywiście nie radzę robić. :) Trzeci krok to konfiguracja kontekstu Crowd.

<Context path="/crowd" docBase="/var/lib/tomcat-6/atlassian/crowd-webapp" debug="0">
    <Resource name="jdbc/CrowdDS" auth="Container" type="javax.sql.DataSource"
            username="user"
            password="pass"
            driverClassName="org.postgresql.Driver"
            validationQuery="select 1"
            url="jdbc:postgresql://localhost:5432/database"/>

    <ResourceLink name="mail/Session"
            global="mail/Session"
            type="javax.mail.Session" />
</Context>

W miejscu docBase należy podać folder w którym znajduje się crowd. Kopiujemy plik crowd.xml do katalogu $TOMCAT_HOME/conf/Catalina/localhost. Ok wygląda na to, że to wszystko co było potrzebne, zatem teraz restart Tomcata i powinno działać.. Powinno, ale nie działa. Problem, z którym męczyłem się bardzo długo to niewidoczny zasób jdbc/CrowdDS w procesie instalacji. O dziwo mail/Session był widoczny. Przy pierwszym podejściu poddałem się i skonfigurowałem połączenie w instalatorze podając te same dane co w konfiguracji kontekstu. Jednakże, po chwili zastanowienia i tych samych problemach z JIRA postanowiłem powtórzyć proces. Logi wskazywały że data source nie uruchamia się, ponieważ pojawiały się wpisy WARN o nieodnalezionej klasie. Poszperałem i dowiedziałem się że potrzebuję biblioteki tomcat-dbcp.jar, której oczywiście nie ma w dystrybucji. Całe szczęście znalazłem w serwisie Java2S. Po ściągnięciu zipa, należy go rozpakować i skopiować tomcat-dbcp.jar do $TOMCAT_HOME/lib.

Instalacja CROWD

Status aplikacji powinien być widoczny w managerze Tomcata. Jeśli wszystko jest w porządku, przechodzimy do instalatora. W pierwszej kolejności zostaniemy zapytani o licencję, następnie o połączenie z bazą danych i sesję mailową. Podajemy zatem co trzeba – ścieżka do data source to java:comp/env/jdbc/CrowdDS a do maila java:comp/env/mail/Session. Konfigurację grup i tak dalej pominę i odeślę do oficjalnej dokumentacji.

Instalacja JIRA

JIRA jako oprogramowanie bardziej wymagające będzie wymagała kilku dodatkowych bilbiotek. Przede wszystkim pobieramy jira-tomcat6-jars.zip. Całość należy wpakować do $TOMCAT_HOME/lib. Następnie pobieramy wersję WAR/EAR:
Pobieranie JIRA
Po rozpakowaniu

unzip atlassian-jira-enterprise-4.0.zip

przechodzimy do katalogu atlassian-jira-enterprise-4.0/edit-webapp/WEB-INF/classes. Musimy tutaj zmienić końcówkę pliku entityengine.xml:

    <datasource name="defaultDS" field-type-name="postgres72"
      schema-name="public"
      helper-class="org.ofbiz.core.entity.GenericHelperDAO"
      check-on-start="true"
      use-foreign-keys="false"
      use-foreign-key-indices="false"
      check-fks-on-start="false"
      check-fk-indices-on-start="false"
      add-missing-on-start="true"
      check-indices-on-start="true">
        <jndi-jdbc jndi-server-name="default" jndi-name="java:comp/env/jdbc/JiraDS"/>
<!-- Orion format: <jndi-jdbc jndi-server-name="default" jndi-name="jdbc/JiraDS"/> -->
<!-- JBoss format: <jndi-jdbc jndi-server-name="default" jndi-name="java:/DefaultDS"/> -->
<!-- Weblogic format: <jndi-jdbc jndi-server-name="default" jndi-name="JiraDS"/> -->
    </datasource>

Poszczególne atrybuty oznaczają:

  • field-type-name – rodzaj bazy danych, wartość postgres72 oznacza PostgreSQL 7.2 i nowsze.
  • schema-name – nazwa domyślnego schematu, trzeba przepisać z PUBLIC, które akceptuje HSQL na public
  • jndi-jdbc/jndi-name – pozostawiamy bez zmian, nasz data source będzie w lokalizacji java:comp/env/jdbc/JiraDS

Pozostaje ustawienie jira.home w pliku jira-application.properties i uruchomienie polecenia build.sh. Po tych krokach tworzymy plik jira.xml w którym zdefiniujemy kontekst tej aplikacji.

<Context path="/jira" docBase="/var/lib/tomcat-6/atlassian/atlassian-jira-4.0.war" debug="0">
    <Resource name="jdbc/JiraDS" auth="Container" type="javax.sql.DataSource"
            username="user"
            password="pass"
            driverClassName="org.postgresql.Driver"
            validationQuery="select 1"
            url="jdbc:postgresql://localhost:5432/database"/>
    <Resource name="UserTransaction" auth="Container" type="javax.transaction.UserTransaction"
            factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60"/>
    <ResourceLink name="mail/Session"
            global="mail/Session"
            type="javax.mail.Session" />
</Context>

Plik kopiujemy do $TOMCAT_HOME/conf/Catalina/localhost. Procedura instalacji powinna przebiegać podobnie jak w przypadku Crowd, czyli podajemy licencję, określamy bazę danych (java:comp/env/jdbc/JiraDS) i kilka kolejnych parametrów.

Instalacja GreenHopper

GreenHopper jako dodatek do JIRA nie wymaga konfiguracji bazy danych. Jedyne co robimy po jego pobraniu to kopiujemy go do $JIRA_HOME/plugins/installed-plugins. Reload kontekstu z managera Tomcata, i przechodzimy do administracji naszym bugtrackerem. W lewym menu szukamy sekcji System/GreenHopper Licence. Po podaniu klucza należy stworzyć projekt. Bez niego nie zobaczymy GreenHoppera w akcji.

Instalacja Confluence

Ostatni krok to instalacja Confluence. Pobieramy dystrybucję WAR/EAR:
Pobieranie Confluence

Tutaj też czeka nas nieco zabawy, ale nie tak dużo. Po rozpakowaniu

unzip confluence-3.0.2.zip

edytujemy plik confluence-3.0.2/confluence/WEB-INF/classes/confluence-init.properties:

confluence.home=/var/lib/tomcat-6/atlassian/confluence-home

Mając to wszystko, możemy spokojnie zająć kontekstem confluence.xml:

<Context path="/confluence" docBase="/var/lib/tomcat-6/atlassian/confluence-3.0.2.war" debug="0">
    <Resource name="jdbc/ConfDS" auth="Container" type="javax.sql.DataSource"
            username="user"
            password="pass"
            driverClassName="org.postgresql.Driver"
            validationQuery="select 1"
            url="jdbc:postgresql://localhost:5432/database"/>

  <ResourceLink name="mail/Session"
            global="mail/Session"
            type="javax.mail.Session" />

</Context>

Plik podobnie jak poprzednie zapisujemy w $TOMCAT_HOME/conf/Catalina/localhost. Po tym wszystkim instalujemy.

Konfiguracja Apache

Skakanie po portach i kontekstach nie jest bardzo wygodne, dlatego też warto skonfigurować Apache i mod_proxy aby wszystko było dostępne z poziomu portu 80, a nie 8080. W ten oto sposób Nexus którego używamy jest widoczny pod adresem repository.code-house.org, a nie localhost:8080. W konfiguracji vhosta umieszczamy:

<IfModule mod_proxy.c>
ProxyRequests On

ProxyPass /jira http://localhost:8080/jira
ProxyPassReverse /jira http://localhost:8080/jira
ProxyPreserveHost On

ProxyPass /confluence http://localhost:8080/confluence
ProxyPassReverse /confluence http://localhost:8080/confluence
ProxyPreserveHost On

ProxyPass /crowd http://localhost:8080/crowd
ProxyPassReverse /crowd http://localhost:8080/crowd
ProxyPreserveHost On

</IfModule>

Podsumowanie

Instalacja tych 3 aplikacji (nie licząc GreenHoppera) zajęła mi praktycznie cały dzień. Przyczyną największych problemów był Tomcat i wszystko inne – czyli np. źle wypakowane archiwum. Diagnostyka z logów Tomcata jest trudna, nie uświadczyłem w nich stack trace z wyjątkiem że nie może połączyć się do bazy. Nie mogłem zestawić również log4j na poziomie kontenera – który kłócił się później z Nexusem, a konfiguracja commons-logging jest jak na moje oko pokręcona. Po tym jak już dowiedziałem się co Tomcat powinien mieć w lib/ poszło z górki. Jeszcze nie zdecydowałem się na integrację JIRA i Confluence z Crowd ponieważ pierwsze podejście było nieudane i JIRA odmówiła uruchomienia się grzecznie zgłaszając java.lang.NullPointerException. :)
Mam nadzieję, że dzięki tej krótkiej instrukcji Wy drodzy czytelnicy nie będziecie mieli tylu problemów.

Older Posts

Typy generyczne od teraz są mniej anonimowe

XML i Adnotacje – kod ogólnego przeznaczenia i JPA

Dwie klasy redukujące ilość kodu w encjach JPA

ServiceMix IDE integration

Javarsovia 2009

Materiały z Eclipse DemoCamp