Monthly Archives: May 2009

Grailsujemy dalej – zadajemy pytania w HowToJava

Po dłuższej przerwie wróciłem do kodowania w Grails. Zostało jeszcze parę rzeczy, by uznać, że na bardzo podstawowym poziomie, przykładowa aplikacja HowToJava jest skończona. Dziś pierwszy krok na tej drodze – możliwość tworzenia tematów/zadawania pytań.

Warstwa widoku, walidacji błędów, klas domenowych nie wychodzi poza rzeczy, której do tej pory opisywałem. Na tym temacie zatem nie będę się specjalnie skupiał. Jedyną rzeczą, którą możnaby przećwiczyć jest kolejny plugin, który zamierzam użyć – FCKEditor. Biblioteka ta jest uniwersalnym GUI przeznaczonym dla stron internetowych. Umożliwia wyczynianie cudów z wpisywanym tekstem – dla potrzeb mojej aplikacji jest tego aż nadto. Zainteresowanych samym edytorem mogę odesłać na jego stronę domową. Zaś dla nas bardziej interesująca będzie strona opisująca plugin, który umożliwia wykorzystanie mocy tegoż edytora w Grails.

Standardowo przechodzimy do katalogu z aplikacją i wydajemy polecenie:

grails install-plugin fckeditor

I po chwili możemy cieszyć się kolejną funkcjonalnością w aplikacji. Zainstalowałem wersję 0.9.2, która jest najnowszą, mam zatem nadzieję, że da się z niej korzystać. Kiedy integrowałem swego czasu FCKEditora z Zend Framework miałem trochę zabawy. No i wykrakałem…

Okazuje się, że skrypt ściągający plugin nie rozpakowywuje go odpowiednio. Zatem musiałem wybrać się na stronę pluginu i ściągnąć go dla pewności ręcznie. Następnie plik *.zip trzeba rozpakować do katalogu /plugins, a konkretniej do folderu fckeditor-0.9.2. Zaś w widoku wrzucamy taki oto kod:

<fckeditor:editor
name="question"
width="100%"
height="200"
toolbar="Basic"
fileBrowser="default">
</fckeditor:editor>

No i działa. Wrzuciłem minimalny pasek z narzędziami, ale to można łatwo zmienić. Dla bardziej zaawansowanej konfiguracji polecam przyjrzenie się plikowi fckconfig.js w katalogu z pluginem.
Walidacja jest prosta jak konstrukcja gwoździa (ogranicza się tylko i wyłącznie do walidacji klasy domenowej). Jedynym problemem była data dodania. Jakoś na początku swej przygody z programowaniem dla web pałałem prawdziwą miłością do typu DATETIME w MySQL. Jednakże jakiś czas temu zostałem wyleczony z używania tej kolumny, na rzecz TIMESTAMPA (unixowego). Po prostu wyszukiwanie po kolumnach jest kilkakrotnie szybsze (wartości TIMESTAMP są zapisywane jako INT(11) ), a także sam format TIMESTAMP jest o wiele bardziej uniwersalny – każdy język programowania (no, przynajmniej te w których kodowałem) miał bardzo sympatyczne wsparcie dla tego formatu. W Javie obecny TIMESTAMP (uwaga: konkretnie chodzi mi o ilość sekund od 1970, a nie milisekund, co zresztą w kodzie widać) można wydobyć w taki sposób:

Math.round( System.currentTimeMillis()/1000 )

I takim oto szybkim obejściem dało się to załatwić. Tak wygląda widok dodający nowy temat:

dodawanieTematu

Advertisements

SCJP, podejście drugie

Jestem po lekturze drugiego rozdziału podręcznika do SCJP. Zasadniczo czyta się to to świetnie, czuć, że pisali to Amerykanie 🙂 No ale do rzeczy.

Zasadniczo popełniłem pewien grzech – stwierdziłem bowiem, że o samym egzaminie doczytam sobie przy okazji. Oczywiście wiem ile trwa, wiem ile pytań czy jaki jest próg zdawalności. Dziś jednakże doczytałem co trzeba i bardzo dobrze zrobiłem. Nie wiedziałem bowiem, że w przypadku normalnego egzaminu przy pytaniach ‘zaznaczanych’, jest podana ilość prawidłowych odpowiedzi. W podręczniku (w testach na końcu rozdziału) informacja ta nie jest podawana, a to wszystko w celu zwiększenia skuteczności nauki. Przy wypełnianiu dzisiejszego testu z rozdziału drugiego (konstruktory, podstawy OOP, metody statyczne) wiadomość ta okazała się bardzo miła. Głównie ze względu na fakt, iż często odpowiedzi to informacja, że coś się wykrzaczy (Runtime Exception) w linii X, Y, Z, albo też nie skompiluje się wcale. No i teraz w końcu co zaznaczyć? Linię z błędem, odpowiedź, że się nie skompiluje cały program, czy może obie? Znając ilość prawidłowych odpowiedzi cały proces staje się łatwiejszy.

A cóż dzisiaj z bardziej ciekawych zagadnień i problemów? Ano kilka – głównie pewnych szczegółów, których na co dzień się po prostu nie zauważa. Oto one:

  • znów var-argsy – tutaj się naciąłem. Dotyczy to również metod statycznych. Fragment kodu:

    static void sifter(A[]... a2) { s += "1"; }
    static void sifter(B[]... b1) { s += "2"; }
    static void sifter(B[] b1) { s += "3"; }
    static void sifter(Object o) { s += "4"; }

    I teraz do tego są wywołania metody sifter z różnymi parametrami. Nauka z tego fragmentu jest taka: 1. przy przeciążanych metodach te, które posiadają jako parametr var-args są prawie zawsze brane pod uwagę na samym końcu!!! (tak piszą w podręczniku). Nie miałem o tym pojęcia więc na pytaniu poległem. 2. dodatkowo warto pamiętać, że tablice, mimo iż zawierają jakąś ilość obiektów, również same z siebie są obiektem.

  • polimorfizm dotyczy tylko metod – o co chodzi już wyjaśniam. Przykład z książki:

    public class test {
    public static void main(String[] args) { new test().go(); }
    void go() {
    Mammal m = new Zebra();
    System.out.println(m.name + m.makeNoise());
    }
    }

    class Mammal {
    String name = "siersc ";
    String makeNoise() { return "jakis odglos"; }
    }

    class Zebra extends Mammal {
    String name = "pasy ";
    String makeNoise() { return "meczy"; }
    }

    No i co się pojawi na wyjściu? Ano właśnie – siersc meczy – polimirfizm to domena tylko metod, jak widać własności to nie obejmuje. Drugą kwestią w tym punkcie jest również to, iż w przypadku metod nadpisywanych(overriden) pierwszeństwo ma nie typ referencji do obiektu, ale typ obiektu, na który dana referencja wskazuje. Czyli w przypadku własności widzimy ssaka (Mammal), ale już w przypadku metody mamy zebrę.

To chyba tyle. Przyznaję, że ciekawie się robi, zaś jedyny problem to fakt, iż kolejne rozdziały stają się coraz dłuższe 🙂

Chlebik walks alone – deployment HowToJava

Zgodnie z zapowiedziami dorobiłem się w końcu własnej przestrzeni w necie. Do tego przestrzeni całkiem sympatycznej bo z własnym Jetty i paroma innymi rzeczami. Rzecz jasna trzeba było spróbować ponownie pokazać światu moje Grailsowe wypociny.

Samego procesu deploymentu do tej pory nie ruszałem. Lokalnie uruchamianie aplikacji odbywa się poprzez NetBeans, zapędów do konfiguracji serwerów/kontenerów też póki co nie mam. Jak wspomniałem również wcześniej – niedługo Helion wyda na podobne tematy książkę, zatem poczekam jeszcze trochę by zapoznać się z tematem dogłębniej. Jednakże by wrzucić coś na serwer docelowy z całą pewnością wypada skonfigurować dostęp do bazy danych. Oczywiście by to osiągnąć wypada wpisać odpowiednie dane dostępowe do DataSource.groovy.

Kiedy się z tym uporałem przyszedł czas na zbudowanie paczki dystrybucyjnej. W Grails jest to proste jak konstrukcja gwoździa. Wystarczy przejść do katalogu z aplikacją i wydać polecenie:

grails war

Pomieli, przemieli i ostatecznie w tymże katalogu wypluje nam paczkę (plik z rozszerzeniem *.WAR). Teraz ten plik (ja jego nazwę zmieniłem na howtojava.war, wyrzucając numerację wersji) należy wrzucić na serwer produkcyjny. Domyślnie Jetty wszystkie aplikacje próbuje odnaleźć w katalogu /webapps. Konwencja ta jest słuszna, zatem w tymże katalogu stworzyłem następny (o nazwie a jakże howtojava) i do niego wrzuciłem plik WAR. Teraz przyszedł czas na konfig serwera.

Należy zajrzeć do pliku jetty.xml, który rezyduje w podkatalogu /etc podstawowego folderu serwera. Możemy z góry określić wspólną konfigurację dla serwera (jak np. uruchamia się na nim jedną aplikację) – i to są ustawienia domyślne. Ja jednakże postanowiłem, iż dla każdej aplikacji (na razie jedna, ale może będzie i więcej) będę posiadał oddzielny plik konfiguracyjny. Wyedytowałem plik i dodałem takie oto zapisy:

<Call name="addLifeCycle">
<Arg>
<New class="org.mortbay.jetty.deployer.ContextDeployer">
<Set name="contexts"><Ref id="Contexts"/></Set>
<Set name="configurationDir"><SystemProperty name="jetty.home" default="."/>/contexts</Set>
<Set name="scanInterval">5</Set>
</New>
</Arg>
</Call>

W folderze z Jetty należy utworzyć wskazany katalog (/contexts). I następnie wrzucamy do niego pliczek o wdzięcznej nazwie Howtojava.xml. Wygląda on tak:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<configure class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="contextPath">/howtojava</Set>
<Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/howtojava/howtojava.war</Set>
</configure>

Jednakże przy takiej konfiguracji, wejście na podstawową domenę powoduje brzydkie zgłoszenie błędu 404 i wylistowanie wszystkich dostępnych kontekstów. Dlatego tez dodałem jeszcze jeden plik w katalogu /contexts – default.xml. Oto on:


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<configure class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/howtojava/howtojava.war</Set>
</configure>

Dzięki temu domyślnie wskazanie na domenę leci pod konkretny adres. Uruchomienie serwera to odpalenie pliku start.jar z odpowiednimi uprawnieniami. Mój jakże miły admin (choć nie wiem czy to on, czy po prostu lekko wyedytował defaultowe skrypty) dostarczył mi 2 pliczki, które opakowywują uruchamianie i zamykanie serwera: Start.sh:

#!/bin/sh

export port=$(expr $(cat base_port) + 0)

echo "Starting the Jetty process at port $port"

nohup java -Xmx$(cat ram_size)m -Drun.mode=production -Djetty.port=$port -jar -server start.jar etc/jetty.xml >> logs/std.out 2>> logs/err.out &
echo $! > prod.pid
echo "The PID is $!"

Nie jest to nic skomplikowanego. Obok tego pliku w katalogu leżą 2 inne pliki – jeden (base_port) zawiera informację o porcie, na którym ma być uruchomiony serwer, a drugi (ram_size) to wejściowa ilość RAMu dla serwera. Przypisany ID procesu jest zapisywany do pliku, a wyjście zarówno System.out, jak i strumień błędów są przekierowywane do odpowiednich katalogów. Drugi skrypt to po prostu odczytanie zapisanego ID procesu z pliku i zabicie tego procesu. Uwadze polecam również plik /bin/jetty-service.conf, gdzie można znaleźć kilka ciekawych zmiennych, którymi można się pobawić.

I tyle. Teraz wystarczy odwiedzić : pewien adres by zobaczyć jak śmiga HowToJava. Subdomena póki co mi nie chwyciła, ale jak załapie to z całą pewnością przepnę ją na nowy adres.

Gdyby ktoś był zainteresowany hostingiem dla aplikacji Grails i bardzo profesjonalną obsługą, wówczas wystarczy napisać mejla na adres admin@serenity.org.pl i ładnie poprosić o ofertę. Jako, że serwery cały czas są w fazie ‘beta’ (w sumie GMail też jest :), zatem szereg rzeczy jeszcze nie działa tak jak powinno, a części póki co nie ma. Ale ceny bardzo konkurencyjne, zaś z jakości usługi jestem póki co bardzo zadowolony.

Chyba zaczniemy przenosiny

Zaczniemy przenosiny. Może inaczej – ja zacznę. Od dziś mój blog jest dostępny również pod adresem chlebik.pl i ta właśnie domena staje się moją oficjalną. Niedługo pod subdomeny podepnę inne projekty. Relacje z walki z wykupionym hostingiem opiszę pewnie jeszcze dziś w nocy, ale póki co wszystko działa dobrze – HowToJava powróci dziś do sieci. Co więcej – przemysliwuję nad migracją całego bloga na wykupiony hosting, z pewnością polepszy to funkcjonalność (choćby to nieszczęsne formatowanie kodu).

Nic nie robi, a się robi

A taki śmieszny tytuł mi dziś do głowy przyszedł. A wziął się stąd, że im mniej piszę, tym większy ruch na blogu. Ciekawe i polecam do przemyśleń filozoficznych.

No ale do rzeczy. Zaniedbałem się ostatnio w pisaniu przyznaję. Jednakże to kwestia tylko braku czasu, a nie chęci. Pomagałem kumplowi w projekcie inżynierskim, nadrabiałem zaległości w lekturze czego innego niż dokumentacje i specyfikacje, a także w końcu się wyspałem. Teraz jednakże czas powrócić – skończyłem właśnie lekturę drugiego rozdziału z podręcznika SCJP, moje przemyślenia i wnioski już wkrótce.

Druga kwestia to start mojego wykupionego hostingu. Na razie dostałem na pewno prywatne Jetty, serwer WWW, baze, poinstalowane Grailsy no i zobaczymy co z tego wyniknie. Relacja z wdrażania aplikacji na serwer inny niż lokalny również niedługo. Will Frederico marry Francesca? Stay tuned.*

* Takie śmieszne wtrącenia są częstym elementem w podręczniku do SCJP. Naprawdę czasami wymiatają 🙂

SCJP, podejście pierwsze

Ano tak jak w tytule – po namyśle stwierdziłem, że będzie całkiem nieźle posiadać ten certyfikat. W związku z tym, iż ostatnimi dniami żona kończyła pisać magistra, zatem dostępu do netu nie miałem, postanowiłem przerobić pierwszy rozdział podręcznika SCJP.

Traktuje on o podstawach podstaw – nazewnictwo, deklaracje, typy wyliczeniowe. Mimo to popełniłem w teście końcowym kilka błędów, choć nie wynikały one z braku wiedzy dotyczących klas abstrakcyjnych 🙂 Taki też zresztą będą miały charakter wszystkie wpisy, które na blogu pragnę poświęcić SCJP. Przepisywanie podręczników, albo też tego, co można znaleźć gdzie indziej (adresy podałem w poprzednim wpisie o SCJP) mija się z celem. Wymienię tylko rzeczy, ktore mnie zaintrygowały, albo z krótymi miałem problem podczas częściowego egzaminu na zakończenie każdego rozdziału.

W tym przypadku są to 3 rzeczy:

  • pusta pętla for – o tym, że pętla ta może być pusta nie trzeba nikogo informować, ale że może być pusta w taki oto sposób, no cóż, to coś nowego:
    for(int __x = 0; __x < 3; __x++);
  • zmienna ilość parametrów metody – w PHP można wpisać dowolną ilość przekazywanych do metody parametrów. Byleby wartości były podane przy wywołaniu metody, albo też miały nadane wartości domyślne w deklaracji metody. W Javie wygląda to inaczej, ale od wersji 5 istnieje fajne usprawnienie. Oto one:

    static void doStuff(int... doArgs) { }

    Pozwala to na przekazanie do metody nieograniczonej liczby argumentów (lub zero) o konkretnym typie. Jedyne obostrzenie to fakt, iż jeśli w deklaracji metody wystepują inne parametry, wówczas taka konstrukcja musi znaleźć się na końcu listy parametrów.

  • “rozstrzelona” deklaracja tablicy – poniższa konstrukcja jest jak najbardziej poprawna. Konkretnie chodzi o utworzenie tablicy dwuwymiarowej.
    Boolean [] tablica [];

Krew, pot i łzy

Do krwi to może jeszcze trochę brakuje, ale pot był (łzy pominąłem). Konkretnie postanowiłem zakupić sobie więcej RAMu. Komputer w domu ma już 1,5 roku, a był kupowany z myślą tylko o programowaniu i internecie (na gry nie mam niestety czasu). I dopóki jedyną rzeczą do odpalenia było IDE do PHP i FF to dawało radę. Ostatnio jednak przestało.

Wiadomo, sam Netbeans potrafi pamięci pożreć, do tego kiedy odpali się w tle dwie konsole, dwie przeglądarki, winampa i kilka komunikatorów, wówczas zaczyna nam trochę to wszystko mulić. Do tego zakładam, że w najbliższej przyszłości zacznę bawić się innymi serwerami JEE, a one to raczej na 100MB pamięci nie skończą. Chciałem też uniknąć sytuacji jaką miałem z poprzednim komputerem (choć fakt, on już staruszek był), gdzie kupienie pamięci było koszmarem, gdyż to były stare SDRAMy, głównie wyrabiane po 256MB.

Mnie generalnie sprzęt jakoś nie lubi ostatnimi czasy – a to dysk mi padł w zeszłym roku (w tym samym komputerze, z którego piszę, ledwo 2 tygodnie po dostarczeniu), kilka miesięcy temu padł mi system w służbowym laptopie (God Bless SVN), a teraz instalacja pamięci. Pewnie wynika to z braku wprawy (robiłem to 2 raz w życiu), ale tego, kto tak rozmieszcza elementy na płycie głównej, że nie można tam mocniej chwycić czegokolwiek powinno się powiesić. Po pół godzinie w końcu się udało umieścić te dwie kości w slotach. Paluchy bolą jak cholera, ciężko się pisze nawet, ale satysfakcja jest. Zakupiłem 2GB DDR2 Kingstona i obecnie mam ślicze 3GB pamięci operacyjnej, co z całą pewnością wystarczy na jakiś czas (na nowe wynalazki M$ powinno wystarczyć, choć XP ma mieć wsparcie do 2013 roku więc się nie stresuję). Teraz to można pracować.