Monthly Archives: July 2009

Nowy layout

Po raz kolejny zmieniłem layout, ale teraz to już myślę, że na dłużej. W związku z tym, że znalazłem możliwość ładnego podświetlania składni o czym pisałem tutaj, nie jestem już zmuszony do stosowania szablonu, który ma najbardziej czytelnie formatowanie bloków <code></code>. Stąd i zmiany na inny szablon spośród dostępnych na serwerach WordPressa. Kierowałem się przede wszystkim szerokością głównego okna aplikacji – teraz jak zresztą widać formatowany kod nie gnieździ się w wąskiej kolumnie, ale ma możliwość rozwinięcia się na całkiem sporą szerokość.

A próżności trochę

Przez przypadek natknąłem się na infostronkę o JDD. A tam konkursik robią 🙂 Jako że dość próżną jednostką jestem to zgłosiłem swojego bloga w walce o zwycięstwo i stąd też mała akcja reklamowa – jeśli uważacie, że mój skromny blog coś wnosi dobrego do polskiej blogosfery to nie czekajcie – każdy głos się liczy!!!!!.

ProgramBash czyli o programowaniu na wesoło

Przed urlopem umieściłem informację o nowym projekcie, który zamierzam zrealizować w ramach nauki Javy. Padło na JSF, Hibernate i RichFaces. Powstała kategoria ProgramBash, która jest jednocześnie nazwą aplikacji. A o co w niej konkretnie chodzi? Wszyscy znają portale takie jak http://bash.org.pl, czy http://demotywatory.pl – ja z kolei wpadłem na pomysł by użyć podobnego konceptu do publikacji śmiesznych/ciekawych fragmentów kodu, albo też sytuacji z życia zespołów programistycznych. Nie jest to zbyt skomplikowane, ale na pewno jest dobrym pomysłem na “edukacyjną” aplikację.

Oczywiście jak zawsze trzeba wyjść od wyglądu. Ja tak jakoś mam, że w projektach, które tworzę na bloga lubię pracować od razu na gotowym szablonie graficznym – od samego początku mogę publikować ładne screeny i mam większe pojęcie o tym jak ostatecznie będzie wyglądać aplikacja. Tym razem wybrałem ciekawy layout, który pobrałem ze strony free-css-templates.com o nazwie redbusiness. Mając zaś gotowy layout pora na przemyślenie ogólnej koncepcji serwisu. Generalnie na pewno będzie możliwość dodawania wpisów (odkrywcze), ich kategoryzacji, przeglądania według różnych kryteriów oraz oczywiście oceniania. Zasadniczo nie wyjdzie to w jakiś znaczący sposób poza CRUDa, choć może zerknę edukacyjnie w stronę webservice. Dla własnego rozwoju rzecz jasna.

Pierwotnie celem tego wpisu było stworzenie krok po kroku funkcjonującej strony głównej, skonfigurowanie Hibernate w stopniu umożliwiającym korzystanie z danych zawartych w bazie, a także zrobienie czegoś ładnego z RichFaces. Jednakże jestem przeciwny publikacji kolubryn na kilkadziesiąt stron, zatem ten wpis na razie zostanie poświęcony tylko ogarnięciu widoku i layoutu, a także zapoznanie się z pakietem Apache Tiles.

Operować zaczniemy na przykładzie, który już wcześniej stworzyłem. Jak już pisałem wcześniej JSF ma to do siebie, że w czystej postaci niewiele jest w stanie zdziałać. Dotyczy to również domyślnych metod renderowania widoku i ogarnięcia czegoś tak prozaicznego jak layout. W mojej książce mądrzy ludzie napisali, iż mamy w tej materii do wyboru dwie drogi. Pierwsza z nich zakłada tworzenie kodu w formie old-JSP, a mi brzydko się ona kojarzy z instrukcją require_once z PHP. W sumie i nic dziwnego, gdyż metoda ta zakłada stworzenie oddzielnych widoków – np. górnej belki, menu, czy stopki. Zaś następnie należy takowe importować (poprzez używanie znacznika c:import z biblioteki JSTL). Nie jest to dobre rozwiązanie.

Drugie podejście wiąże się z użyciem pakietu Apache Tiles. Cały ten pakiet służy właśnie temu, aby przede wszystkim za pomocą tzw. “kafelków” (stąd nazwa), zarządzać widokami w aplikacji javowej. Należy odwiedzić oficjalną stronę pakietu i ściągnąć najnowszą wersję – 2.3.1. Następnie wypakować wszystkie pliki JAR z archiwum (z głównego katalogu oraz podkatalogu /lib) i wrzucić do katalogu WEB-INF/lib w naszej aplikacji. Tak twierdzi dokumentacja. Następnie trzeba poinformować naszą aplikację (poprzez plik web.xml) o serwlecie, który będzie nam potrzebny. Do tego pliku dopisujemy taki kod:

<servlet>
<servlet-name>tiles</servlet-name>
<servlet-class>org.apache.tiles.web.startup.TilesServlet</servlet-class>
<init-param>
<param-name>
 org.apache.tiles.definition.DefinitionsFactory.DEFINITIONS_CONFIG
</param-name>
<param-value>
 /WEB-INF/tiles-defs.xml
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

Run aplikacji… ZONK. Oczywiście krzyk, że nie potrafi odnaleźć takiej klasy jak org.apache.tiles.web.startup.TilesServlet. PPM na elemencie library w projekcie i dodanie ww. plików JAR załatwiło sprawę. Apache Tiles wstępnie skonfigurowane.

Zabawa z konfiguracją kafli dopiero się zaczyna. Pomysł generalnie jest taki – tworzymy na razie jeden plik z layoutem przeznaczony dla użytkowników niezalogowanych w serwisie. Taki plik layoutu będzie nam renderował górne menu, główną zawartość konkretnej strony oraz stopkę. Nad wyhaczeniem co z czym spędziłem chyba łącznie 3 godziny. Moja książka do JSF jedno, dokumentacja co innego, a praktyka pokazała jeszcze co innego. Masakra. Generalnie jak widze najlepszym przyjacielem jest NetBeans, który podpowiada co w danej sytuacji/tagu można wpisać – podpowiedzi z definicji działają. Koniec gadania – oto co trzeba zrobić:

  • XML – czyli musimy dopisać odpowiednie zapisy konfiguracyjne w pliku WEB-INF/tiles-defs.xml
  • wrzucić CSS oraz obrazki do niego
  • zaimplementować wygląd kafelka w formie pliku(ów) JSP
  • wrzucić wygląd do konkretnej strony JSP, którą chcemy wyświetlić

Jak wygląda layout już wiadomo. Plik konfiguracyjny powinien zatem wyglądać mniej więcej tak:

<tiles-definitions>
<definition name="guestLayout" template="/WEB-INF/layout/guestLayout.jsp">
<put-attribute name="upperMenu" value="/WEB-INF/layout/upperMenuTemplate.jsp" />
<put-attribute name="content" />
<put-attribute name="footer" value="/WEB-INF/layout/footerTemplate.jsp" />
</definition>
</tiles-definitions>

W tym kroku tworzymy definicję – czyli określamy pewien abstrakt widoku, który otrzymuje stosowną nazwę, wiążemy go z konkretnym widokiem istniejącym gdzieś w formie pliku JSP, a także nadajemy mu atrybuty, którym również przypisujemy nazwy i wartości (kolejne odwołania do plików JSP). Uwaga! Nalezy zwrócić uwagę, że wszystkie ścieżki podajemy bezwzględnie (zaczynamy je znakiem ‘/’), a korzeniem jest folder web. Może pojawić się pytanie – dlaczego elementy layoutu umieszczamy w katalogu WEB-INF? To dość proste – by nie można było się do nich dostać pojedynczo poprzez przeglądarkę.

Stworzyłem plik guestLayout.jsp. Pytanie kolejne! Jakie ścieżki wpisać w sekcji HEAD naszej strony layoutu? Choćby by dobrać się do plików CSS lub JSa? Ano i tutaj mała niespodzianka – podajemy ścieżkę względem katalogu web, jednakże nie traktując go jako korzenia. Oto jak to wygląda u mnie:

	<link rel="stylesheet" type="text/css" href="css/style.css" media="screen" />

Rzecz jasna utworzyłem sobie folder css, aby nie wprowadzać niepotrzebnego bałaganu. CSS na pewno mamy już podpięty, ale co w takim razie zrobić z grafiką w projekcie? Obrazki z layoutu wrzuciłem również do katalogu web do utworzonego specjalnie w tym celu podkatalogu images. By jednakże były one przez nasz plik CSSa widoczne, musimy ich adresowanie z poziomu reguł CSSa potraktować relatywnie. Czyli wygląda to choćby tak:

#wrap #menu li { line-height: 26px; background: #F6F6F6 url(../images/li-line.gif) no-repeat bottom left;}

Uporawszy się z tymi zagadnieniami pora spojrzeć na plik guestLayout.jsp. U mnie wygląda on tak:

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>

<%@taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@taglib uri="http://richfaces.org/rich" prefix="rich"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<f:view>
<html>
    <head>
        <title>ProgramBash</title>
        <meta http-equiv="Content-Language" content="Polish" />
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="author" content="Michał 'Chlebik' Piotrowski" />
        <meta name="Robots" content="index,follow" />
        <link rel="stylesheet" type="text/css" href="css/style.css" media="screen" />
    </head>

    <body>
       
        <tiles:insertAttribute name="upperMenu" />
  
        <div class="content">
                        
            <div id="main">
               
                <div id="left_side">
                                        
                    <div class="rs">
                         <tiles:insertAttribute name="content" />
                    </div>
                </div>
        
                <tiles:insertAttribute name="footer" />

            </div>
    </body>
</html>
</f:view>

Nie ma tu niczego odkrywczego z wyjątkiem elementów <tiles: >. Ano służą one w tym miejscu do “wrzucenia” pewnych konkretnych atrybutów – czyli w naszym przypadku po prostu kolejnych widoków, które znajdują się w plikach JSP. Atrybuty o nazwach upperMenu oraz footer zostały przyporządkowane do plików JSP w deklaracji definicji widoku w pliku tiles-defs.xml. Jednakże pozostawiliśmy tam wolne miejsce dla atrybutu content, tzn. nie przypisaliśmy mu żadnego widoku. I tak miało być! Albowiem ten atrybut będzie reprezentował bieżący widok, który jest różny dla każdego requestu (no może nie każdego, większości).

Docelowo operowałem na pliku welcomeJSF.jsp, który leży sobie od samego początku w katalogu web. Wystarczyło przeredagować go na taką formę:

<%@taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@taglib uri="http://richfaces.org/rich" prefix="rich"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insertDefinition name="guestLayout" flush="true">
<tiles:putAttribute name="content" value="/glowna/content.jsp" />
</tiles:insertDefinition>

I przy posiadaniu takiej struktury plików:

strukturaProjektuJSF

Ostatecznie mym oczom ukazał się taki jakże miły każdemu sercu widok:

glownaProgramBash

To tyle na dziś. Wygląda to bardzo łatwo i skromnie, ale przyznaję, że trochę czasu nad rozkminianiem tego spędziłem. Zadziwiająco mało momentami Google wie na temat JSF i ewentualnych jego bugów czy współpracy z innymi technologiami. Oby się to zmieniło.

GIT majonez czyli kontrola wersji z Linusem w tle

Dziś będzie o czymś innym. Jakoś do tej pory w swoich wpisach nie wychodziłem poza zagadnienia związane z samym programowaniem lub biliotekami użytecznymi przy tymże programowaniu. Jednakże prędzej czy później przyjdzie czas na zabawę z bardziej rozbudowanymi narzędziami z Javowego swiata – wtedy też i pewnie zacznę popełniać więcej wpisów na te tematy. W związku z małą rewolucją u mnie w zakładzie pracy chronionej 🙂 przeszliśmy na Git-a. Jako, że miałem z jego instalacją na Windows małe przygody (chodziło głównie o autoryzację przez LDAP), postanowiłem przedstawić historię tych zmagań na blogu – pewnie komuś się przyda.

Na początku kilka słów o samym Gicie. Ten system kontroli wersji powstał jako dzieło programistów kernela, a konkretniej jak podaje Wiki samego Linusa Torvaldsa. Został on stworzony na potrzeby prac nad jajkiem kiedy poprzednio używany system przestał być darmowy. W mojej firmie powodem odejścia od stosowania SVNa była jego niezbyt udana polityka dotycząca oddzielnych gałęzi oraz ich mergowania. W przypadku Gita praca jednocześnie nad wieloma gałęziami i efektywne ich łączenie była jednym z fundamentalnych założeń dla całego systemu.

Oczywiście Git jako rzecz zaprojektowana do pracy w środowisku POSIX na Windowsie nie za bardzo chce działać. Jednakże na pomoc przychodzi nam programik msysgit. Ściągamy go z hostingu Googla po czym rozpoczynamy instalację. Jedynym ciekawym jej wyróżnikiem w przypadku systemu Windows jest pytanie o końcówki linii jakie mają być stosowane przy obsłudze repozytorium. Jeśli ktoś miał (nie)przyjemność pracować na jednym repozytorium SVN z ludźmi uzywającymi w pracy linuxa z pewnością doceni ten jakże oczywisty bonus. Instalator ostatecznie umieści u nas na dysku konsolę do obsługi Gita opartą na Cygwinie, a także GUI, które ma być nakładką na konsolę. Jedno i drugie ma swoje plusy i minusy, choć trzeba przyznać, że funkcjonalność konsoli jest o niebo większa.

Domyślnie repozytorium zostało założone na lokalnych serwerach, do których dostęp po SSH (tak miało być) jest autoryzowany LDAPem. No i teraz co po kolei trzeba zrobić, aby to wszystko działało.

1. Generjemy klucz publiczny i prywatny jeśli ich nie mamy. W przypadku Windowsa najlepiej do tego użyć PuttyKeyGen. Generujemy klucz po czym zapisujemy oba klucze (publiczny i prywatny).

2. Putty stosuje własny format pliku do trzymania klucza. Dlatego też by format naszego klucza działał z innymi usługami należy posłużyć się ponownie aplikacją KeyGenerator i otworzyć zapisany klucz prywatny. W górnej części okienka znajduje się pole, w którym zostanie pokazany klucz publiczny w formacie umożliwiającym wrzucenie go do listy uprawnionych kluczy.

keyGen

Ten właśnie klucz (skopiowaną zawartość pola) wrzucamy w panelu zarządzania kluczami/katalogu na serwerze SSH czy jakiekolwiek tam rozwiązanie jest u nas przyjęte.

3. Istnieje szansa, że będzie musiało minąć trochę czasu zanim klucz publiczny rozpropaguje się po wszystkich serwerach (ale to pewnie rzecz w konfigu lokalnym), zależy to od ilości serwerów, na których ten klucz będzie w użyciu.

4. Następnie ze strony downloadu Putty ściągamy aplikację o nazwie Pageant, która jest agentem połączeń SSH dla Putty, a także dla Plinka, która to aplikacja również jest częścią rodziny Putty i u mnie podczas instalacji msysgita wybrałem ją jako tę, która ma obsługiwać połączenia SSH.

5. Uruchamiamy wspomnianego Pageanta, który zadokuje się jako mała aplikacyjka w tle (komputer w kapeluszu).

dock

Klikamy na ikonkę po czym dodajemy nasz klucz prywatny do listy i viola – teraz możemy odpalić konsolę Gita i z czystym sumieniem móc połączyć się po SSH z docelowym serwerem i np. sklonować istniejące repozytorium. That’s all folks.

O motywacji i celach

Wakacje w pełni. Przyznaję, że po urlopie zabranie się do jakiejkolwiek pracy “po pracy” jest dla mnie niemiłosiernie wręcz trudne. Może i wina w tym żony, która po ukończeniu hardkorowego czerwca (bardzo ciężkie egzaminy, całe szczęście zdane z celującymi wynikami) daje się zabrać na spacer 🙂 Rzecz też pewnikiem w tym, że nazbierało się kilka większych rzeczy, które trzeba w końcu ruszyć – kwestia w tym, iż większe, czyli wymagające więcej wysiłku. A może to po prostu pogoda? W końcu przestało grzmieć co wieczór – widok błękitnego nieba do wytężonej pracy nie nastraja.

Aktywnością, której się poświęciłem, aby zebrać się w końcu w sobie było posprzątanie na dyskach twardych. Co prawda czeka mnie jeszcze małe przemeblowanie w partycjach, ale co mogłem posprzątać, posprzątałem (w myśl mądrego miejscami Feng-Shui – kiedy chce się coś zmienić – wpierw trzeba posprzątać, choćby biurko ). Defragment dysków, zainstalowany CrystalClear (a co, pięknie moje okienka wyglądają), porządek w folderach i w plikach. Przy okazji tego przemeblowania znalazłem zakurzoną kompilację kilku cytatów z Akwarium i Specnazu Wiktora Suworowa. Jako, że dawno temu zapisałem je ku własnej motywacji ( siedzenie nad PHP do 4 nad ranem po 12h pracy zarobkowej wymagało motywacji jak cholera ), obecnie również powinny zdać egzamin. Wklejam je zatem – może i kogoś do pracy natchną.

Możliwości człowieka są nieograniczone. Człowiek może osiągnąć w swoim życiu wszystko. I to w każdej sferze ludzkiej aktywności. Ale żeby zwyciężyć swych przeciwników, człowiek musi najpierw pokonać samego siebie, przezwyciężyć strach, niepewność, lenistwo. Rozwój – to ciągła walka z samym sobą. Człowiek powinien się zmusić, aby wstawać wcześniej i kłaść się spać później od innych. Człowiek musi wyeliminować ze swego życia to wszystko, co przeszkadza mu w osiągnięciu zaplanowanego celu. Musi podporządkowywać cały swój byt najsroższemu reżimowi. Powinien wykorzystywać swój czas z największym zaangażowaniem, jakie tylko jest możliwe, a nawet robić to, co wykracza poza te ramy.

Człowiek dążący do swego celu może być skuteczny tylko w przypadku, jeśli każdą minutę swego życia wykorzysta z maksymalną korzyścią dla osiągnięcia zaplanowanego celu. Jeśli stworzył dla siebie system kar i karze sam siebie za każdą zmarnowaną minutę. Człowiekowi w zupełności wystarczą 3-4 godziny snu, cały pozostały czas może być wykorzystany dla osiągnięcia upragnionego celu.

Każdy trening ma sens tylko w tym przypadku, jeśli doprowadza on człowieka na skraj jego sił fizycznych i psychicznych. […] Trening spełnił swoje zadanie tylko wtedy, jeśli doprowadził człowieka do granic jego możliwości, kiedy zgrzyta on zębami, niemalże rwie swe mięśnie, a twarz wykrzywia potworny grymas.

Mistrzem staje się tylko ten, który na każdy trening idzie niczym na śmierć, na swój ostatni bój, w którym polegnie albo zwycięży. […] Zwycięzcą będzie ten, dla którego zwycięstwo jest droższe od życia. […] Ten kto zwycięży siebie, może pokonać każdego. Zwyciężać innych jest znacznie łatwiej. Siebie bardzo trudno.

SCJP, podejście dziesiąte

Jak zwykle po powrocie z urlopu nic się nie chce. Czas w pracy dłuży się niemiłosiernie, do tego ta zwariowana od kilku tygodni pogoda nie polepsza nastroju. Zbierałem się trzy dni zanim postanowiłem znów zawalczyć z tematyką SCJP. Choć to i dobrze, gdyż oto podejście dziesiąte i jak na razie koniec. Ostatni rozdział w podręczniku poświęcony kompilatorowi miałem okazję przerobić już wcześniej. Popełniłem wówczas kilka błędów i temat zostawiłem do późniejszy. Jednakże teraz po powrocie z urlopu ponownie zapoznałem się z zawartością tych kilkunastu stron i tym razem test poszedł o niebo lepiej.

Mimo to należy do pytań dotyczących kompilacji podchodzić ostrożnie, podobnie jak do pytań dotyczących operatorów. Pozornie łatwe potrafią tak naprawdę bardzo łatwo wywieść na manowce. Zwłaszcza dlatego, iż obecnie raczej całą sprawę z kompilacją, classpathem i innymi tego typu rzeczami załatwia nam IDE, zatem raczej nikt nie jest za pan brat z dyrektywami kompilatora czy zabawą z szukaniem klas (choć może się mylę?). Oto lista kilku rzeczy, na które warto zwrócić uwagę:

  • importy statyczne – oczywiście koniecznym jest ich użycie za pomocą słów kluczowych static import (w takiej kolejności). Jednakże mniej oczywistym zapisem jest to, iż możemy importować w ten sposób nawet pojedyncze stałe i metody.
  • asercje – było o nich w rozdziale piątym, ale nie zaznaczyłem tam rzeczy najistotniejszej. Otóż nalezy pamiętać, że asercje zostały wprowadzone już w wersji 1.4! I dlatego też wywoływanie kompilatora i wirtualnej maszyny w ten sposób:
    javac -source 1.4 plik.java
    java -ea plik
    

    Spowoduje, że kod, w którym występują niespełnione asercje (zwracające wartość false) spowoduje wygenerowanie błędu podczas wykonania programu (czyli po prostu asercje będą działały). Wykonania, nie kompilacji! Powtórzmy – błędy wykonania (run), to co innego niż błędy kompilacji (compile).

  • classpath – czego tak naprawdę dotyczy ta dyrektywa dla kompilatora/JVM? Otóż jej zadaniem jest głównie znalezienie wszystkich klas, których kompilowana/uruchamiana klasa będzie potrzebowała. To jest główne zadanie dla classpath. Pamiętać należy również o tym, iż w przypadku kompilacji (polecenie javac) podanej nazwy pliku do kompilacji poszukuje się domyślnie w bieżącym katalogu. W przypadku uruchamiania pliku tak nie jest! No i rzecz ostatnia – podanie wartości dla classpath powoduje nadpisanie zmiennej systemowej (o ile rzecz jasna istnieje)
  • pliki JAR – archiwa są dość proste do zrozumienia, co więcej, na egzaminie nie ma pytań dotyczących ich tworzenia i zarządzania. Natomiast na pewno trzeba wiedzieć, że po utworzeniu pliku JAR z konkretnego katalogu, nawet po dodaniu go do classpath do klas zawartych w archiwum należy odwoływać się w kodzie poprzez podanie pełnej nazwy klasy (łącznie z nazwą pliku JAR). Oto przykład:
    test |
    plik.uzywajacy.klasy.z.jara
    tutaj.utworzymy.plik.jar
    katalog.do.zjarowania |
    podkatalog1
    podkatalog2 |
    plik.java

    Odwołując się do pliku w archiwum JAR, które utworzyliśmy w katalogu test należy podawać pełną ścieżkę. A zatem nasz plik w katalogu test, w którym chcielibyśmy wykorzystać klasę z archiwum musi odwoływać się do niej poprzez zapis PLIK_JAR/katalog.do.zjarowania/podkatalog2/plik – pomimo dodania pliku JAR do classpath.