Monthly Archives: April 2010

Pierwsze starcie ze smartphonami – HTC Hero na pokładzie

Nadejszła wielkopomna chwila. Z definicji jestem zwolennikiem prostoty i funkcjonalności jeśli chodzi o technologie. Czyli nie widzę potrzeby by posiadać 50 cali telewizora w moim 20m pokoju, czy lustrzanki Sony za kilkanaście tysięcy złotych, kiedy robię zwykłe fotki “rodzinnookolicznościowe”. Tak samo do tej pory było z komórkami – jakieś proste modele, byleby działało. Tym razem jednakże historia się zmieniła.

Postanowiłem bowiem zainwestować bardziej przyszłościowo – od dnia dzisiejszego jestem posiadaczem HTC Hero, co jednakże nie jest aż tak istotne – bardziej chodziło o system operacyjny Android. Powiedzmy sobie szczerze – rynek aplikacji dla komórek i smartphonów będzie rósł cały czas – zwłaszcza w kontekście spekulacji o wypuszczeniu przez Google tabletu, na którym ma również śmigać Android. Dlatego też postanowiłem zakupić urządzenie z tym systemem i za jakiś czas (na pewno po zakończeniu prac nad SCJPTesterem) spróbować swoich sił w programowaniu dla tego urządzenia. Rzecz jasna istnieją symulatory Androida, jednakże czym innym jest stworzenie aplikacji na komputerze, czym innym zaś jest jej używanie w telefonie. By zatem również mieć jakieś pojęcie o użyteczności aplikacji wypadałoby przetestować ją również w telefonie. No i w sumie… ja też mogę trochę przygadżecić (ale potworek słowny) i dostać +15 do lansu na dzielni 🙂

Advertisements

2 ciekawe rzeczy

Darek Zoń tworzy obecnie coś podobnego do SCJPTestera – z tym tylko, iż używa Springa w najnowszej wersji, a także warstwę widoku ogarnia u niego Sitemesh. Zatem dla zainteresowanych tematem polecam odnośnik do pierwszego wpisu z krótkiego HOWTO.

Druga informacja jest baaaardzo miła. Zasadniczo to choruję i siedzę w domu, stąd też i częstotliwość wpisów się zwiększyła. Muszę przyznać, że przynosi to efekty – w dniu wczorajszym pobiłem rekord ilości odwiedzin w skali jednego dnia – obecnie liczba ta to 346. Dziękuję za ten wynik i naprawdę to nie będzie frazes kiedy powiem, iż niesamowicie motywuje to do dalszej pracy. Dzięki raz jeszcze.

SCJPTester w wersji HelloWorld!

Dzisiaj zrobimy coś poważniejszego. Konkretnie postaramy się sprawić, że nasz SCJPTester zaistnieje w sieci, a także sprawimy by owo zaistnienie było czymś więcej niż wyświetleniem zwykłej strony JSP z napisem “Hello World!”. Do roboty.

W tym momencie jednakże nie wiem od czego tak naprawdę zacząć. Może od samego Spring MVC, gdyż to w jego strukturze będziemy się poruszać. Już po nazwie widać, iż realizujemy wzorzec MVC, co jest bardzo dobre, ale co więcej – Spring MVC implenentuje również wzorzec Front Controllera, to znaczy, iż wszystkie żądania skierowane do aplikacji przechodzą przez jedno miejsce (niezależnie od requestu). Poniżej ładny schemat zaczerpnięty ze stron Spring MVC:

Jest mi to wszystko o tyle bliskie, że w codziennej pracy z PHP korzystam z tych samych wzorców. Podoba mi się to również z tego powodu, iż wiadomo gdzie przychodzi nasze żądanie, można z nim po drodze zrobić jeszcze wiele ciekawych rzeczy. O wiele bardziej to przejrzyste niż JSF. Lecimy dalej. Nasz front controller jest najzwyklejszym serwletem, który dziedziczy po klasie HttpServlet i jako taki powinien być zdefiniowany w pliku web.xml. Podstawowa konfiguracja wyglądałaby na przykład tak:


    <servlet>
        <servlet-name>frontcontroller</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>frontcontroller</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

Domyślnie Spring MVC załaduje wszystkie ustawienia z pliku web.xml, jednakże przy każdym requeście (w powyższym przykładzie do zasobów kończących się na .html) zostanie uruchomiony serwlet o nazwie frontController. W tym momencie mechanizm ładujący spróbuje znaleźć w katalogu WEB-INF dodatkowy plik z konfiguracją, według wzoru:

[nazwa-serwletu]-servlet.xml

Dzięki czemu możemy mieć wyspecjalizowany plik kontekstu dla konkretnego typu żądań (np. do takich, które wymagają zwrotu nie HTMLa, ale np. pliku PDF). Generalnie w myśl mojego zamysłu aplikacja będzie posługiwała się rozszerzeniami *.html. Samych stron jakoś specjalnie wiele to nie będzie, dlatego też poprzestaniemy na opisowych nazwach “niby-routingu”, czyli np. login.html czy testuj.html. Request do konkretnego zasobu jest podpinany pod klasę kontrolera, która go obsłuży. Spring dostarcza szereg bazowych klas, które powinny być użyte do obsługi żądań (w sensie – należy po nich dziedziczyć). Dlatego też w pliku frontcontroller-servlet.xml pojawi się taki kod:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <!-- the application context definition for the springapp DispatcherServlet -->

  <bean name="/index.html" class="com.wordpress.chlebik.controllers.IndexController" />

</beans>

I teraz trzeba napisać nasz kontroler. Generalnie jego zadaniem będzie serwowanie zwykłej statycznej strony, zatem nie ma potrzeby korzystać z jakiś bardziej zaawansowanych klas Springa – zaimplementujemy po prostu interfejs Controller, który jest bazowym dla wszystkich klas kontrolerów. O innych klasach implementujących ten interfejs napiszę później przy tworzeniu bardziej zaawansowanej użyteczności:

package com.wordpress.chlebik.controllers;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

/**
 *  Klasa kontrolera dla strony glownej
 *
 * @author chlebik
 */
public class IndexController implements Controller {

 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    return new ModelAndView("index.jsp");
  }

}

Na razie odnosimy się do prostej strony index.jsp, która została utworzona wraz z całym projektem. Jest ona też wpisana w pliku web.xml na liście plików powitalnych dla aplikacji. Po małych przeróbkach z mojej strony plik ten wygląda tak:


<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>SCJPTester</title>
    </head>
    <body>
        <h1>Bardziej rozbudowane Hello World!</h1>
    </body>
</html>

No i po uruchomieniu aplikacji widzimy taki ekran:

Rzecz jasna jest to domyślny start poprzez odwołanie się do domeny localhost:8084, sprawdźmy zaś, czy nasz kontroler daje sobie radę. Odwiedzamy adres localhost:8084/index.html i widok nam się nie zmienił – czyli jesteśmy w domu, kontroler działa. Jednakże jak na razie jest to dość słabe HelloWorld. Dorzucimy do tego przykładu ładny widok – czyli podepniemy FreeMakera wraz z całym layoutem. Na pewno będzie się przyjemniej z tym wszystkim pracowało.

Wpierw zatem trzeba się zatroszczyć o same źródła biblioteki FreeMarker. Odwiedzamy starego znajomego POM.xml i w zależnościach projektu dopisujemy:

 <dependency>
   <groupId>org.freemarker</groupId>
   <artifactId>freemarker</artifactId>
   <version>2.3.16</version>
 </dependency>

I dociągamy tę zależność. Kiedy FreeMarker pojawi się nam na liście bibliotek jesteśmy w domu. Tak w ogóle to zdecydowałem się na tę bibliotekę, gdyż jest ponoć bardzo podobna do Velocity (czyli poznaję prawie 2 rzeczy za cenę 1:) ), a do tego Spring posiada do tego wyprowadzenie (w sensie integracji widoku), ale do tego jeszcze dojdziemy. Co konkretnie robi FreeMarker? Organizuje nam widok – jest to w zasadzie system szablonów – czyli dzięki niemu stworzymy sobie cały layout strony, a także będziemy dzięki niemu operować w widoku na danych, które dostaniemy z modelu. Problem z FreeMarkerem jest taki, że w sieci jest masa tutoriali na temat jego połączenia ze Springiem, jednakże najczęściej na przykładzie 1 statycznej strony się kończy. Takie zaś rozwiązania były dobre przy HTMLu 3 jakieś 10 lat temu, jak nie lepiej. Dlatego też ja pokażę jak przygotować projekt do życia – czyli zbudujemy sobie cały layout, który będzie dynamicznie wypełniany w zależności od wywołanego zasobu. Do dzieła!

FreeMarker jest już w naszej bibliotece. Teraz należy poinformować Springa o jego istnieniu, a także ustawić, że wyświetlamy widok inaczej niż za pomocą czystych stron HTMLa. Zatem odwiedzamy web.xml i klepiemy tam takie coś:

<servlet>
    <servlet-name>freemarker</servlet-name>
    <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>

    <!-- FreemarkerServlet settings: -->
    <init-param>
      <param-name>TemplatePath</param-name>
      <param-value>/WEB-INF</param-value>
    </init-param>
    <init-param>
      <param-name>NoCache</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>ContentType</param-name>
      <param-value>text/html</param-value>
    </init-param>

    <!-- FreeMarker settings: -->
    <init-param>
      <param-name>template_update_delay</param-name>
      <param-value>0</param-value>
    </init-param>
    <init-param>
      <param-name>default_encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>number_format</param-name>
      <param-value>0.##########</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>
  </servlet>

To na początek kilka podstawowych ustawień servletu FreeMarkera. Wartości są dość jasne – warto tylko zwrócić uwagę na parametr template_update_delay – ustawienie tam wartości 0 jest dobre dla środowiska developerskiego. Dla oddzielnych pików layoutu rzecz jasna utworzymy specjalny katalog w folderze WEB-INF, dzięki czemu nie da się otworzyć poszczególnych składowych w przeglądarce. Dla swojej aplikacji jak zawsze skorzystałem z darmowego szabloniku, który można podejrzeć w tym miejscu. Szablonik rzecz jasna posiada coś takiego jak nagłówek, menu, główną treść i content. Dlatego też naturalnie rozbijemy go na kilka oddzielnych części
i ładować potrzebne nam części. FreeMarker składuje szablony w plikach z rozszerzeniem *.ftl. Tworzymy katalog layout w folderze WEB-INF i wrzucamy tam plik layout.ftl:

<#macro scjptesterLayout>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>SCJPTester</title>
        <meta http-equiv="Content-Language" content="Polish" />
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <link href="/css/main.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div id="header">
          <h1><a href="/index.html">SCJPTester</a></h1>
          <ul id="menu">
            <li class="active"><a href="/index.html">główna</a></li>
            <li><a href="/start.html">zarejestruj/zaloguj</a></li>
            <li><a href="#">demo</a></li>
            <li><a href="#">kontakt</a></li> 
          </ul>
        </div>
    
        
      <div class="wrap">

       <#nested />
          

        </div>
        <div id="footer">
          <p class="right">Design: <a href="http://www.solucija.com/">Luka Cvrk</a></p>
          <p>&copy; Nazwa 'SCJPTester' &middot; jest własnością Michała 'Chlebika' Piotrowskiego</p>
        </div>
    </body>
</html>
</#macro>

Jest to zwykły layout (na razie większość linków i menu są dość umowne), w którym jednakże widać kilka nowości. Pierwsza linijka kodu mówi już wiele – tworzymy własne makro, któremu nadajemy określoną nazwę. Całość HTMLa musi być zawarta w treści tegoż makra. W środku do tego, konkretnie w miejscu gdzie będziemy chcieli, aby wyświetlana zawartość zmieniała się w zależności od wybranego zasobu – wrzuciliśmy znacznik: #nested. W tym miejscy FreeMarker wrzuci nam stosowny widok. Pliki z obrazkami oraz CSSem należy wrzucić bezpośrednio do katalogu webapp, dzięki czemu będzie on dostępny z poziomu przeglądarki – bez tego nic ładnego nam się nie pokaże. W katalogu WEB-INF tworzymy także podkatalog views, gdzie będziemy składować poszczególne widoki dla konkretnych akcji. Taki podział wprowadza trochę czystości do widoków, od razu wiadomo gdzie i czego szukać. Teraz do tego musimy poddać edycji plik frontcontroller-servlet.xml i wrzucić tam taki oto kod (zwróć uwagę na zapisy o kodowaniu – mi zeszło na rozkminienie tego 2h):

<bean id="freemarkerConfig"
  class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
  <property name="templateLoaderPath"
   value="/WEB-INF" />

  <!-- To jest niemozliwie wrecz wazne - bez tego bedziemy mieli krzaki w widoku zamiast UTF-8  -->
 <property name="freemarkerSettings"> 
    <props>
         <prop key="default_encoding">UTF-8</prop>
    </props>
 </property>

 </bean>


 <bean id="viewResolver"
  class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
      <property name="cache" value="true" />
      <property name="prefix" value="/views/" />
      <property name="suffix" value=".ftl" />

      <!-- if you want to use the Spring FreeMarker macros, set this property to true -->
      <property name="exposeSpringMacroHelpers" value="true" />

       <!-- To jest niemozliwie wrecz wazne - bez tego bedziemy mieli krzaki w widoku zamiast UTF-8  -->
      <property name="contentType" value="text/html;charset=UTF-8"></property>

 </bean>

Powiadamiamy w ten sposób FreeMarkera gdzie ma szukać plików z szablonami, a także w jakim formacie się to odbędzie (określenia prefix i suffix dla ViewResolvera). W związku z takim określeniem reguł, kod w kontrolerze musimy zmienić na:

 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {


    return new ModelAndView("index");
  }

Dzięki takiemu podejściu przy ewentualnej zmianie koncepcji widoku wystarczy, że zmienimy dane w pliku XML i możemy zmienić katalog, gdzie nasze pliki leżą, że o i ich rozszerzeniu nie wspomnę. Teraz na koniec wystarczy stworzyć plik index.ftl w katalogu views:

<#import "../layout/layout.ftl" as layout>
<@layout.scjptesterLayout>

  <div id="teaser">
      <div class="wrap">
       
        <div class="box">
          <h2>Witaj na stronach aplikacji <em title="SCJPTester">SCJPTester</em></h2>
          <p>Aplikacja ta powstała jako projekt edukacyjny Michała 'Chlebika' Piotrowskiego, w celu praktycznego poznania frameworka <strong>Spring</strong>, a także szeregu innych
          technologii. Projekt powstał niedawno zatem jego funkcjonalność jest na razie znikoma, jednakże stan ten zmienia się bardzo szybko. Więcej informacji na temat aplikacji
          moża znaleźć <a href="https://chlebik.wordpress.com">na blogu autora.</a></p>
        </div>
      </div>
    </div>


      <div class="col">
        <h3>Zarejestruj <span class="red"> się!</span></h3>
        <p>Bardzo szybki i prosty proces rejestracji pozwoli Ci od razu rozpocząć przygotowania do egzaminu.</p>
      </div>
      <div class="col">
        <h3>Kontroluj <span class="red">postępy</span></h3>
        <p>Dzięki panelowi statystyk będziesz mógł sprawdzić swoje postępy w nauce. Wyniki poprzednich testów zostaną zapisane i w każdej chwili można je przejrzeć.</p>
      </div>
      <div class="col last">
        <h3>Zgłaszaj <span class="red">własne pomysły</span></h3>
        <p>Jeżeli zaproponowane pytania nie są dla Ciebie wyzwaniem - stwórz swoje własne i podziel się nimi z innymi użytkownikami serwisu!</p>
      </div>



</@layout.scjptesterLayout>

I jesteśmy w domu. W pierwszej linijce importujemy nasz layout (wskazujemy konkretny plik) do konkretnej przestrzeni nazw, w tym przypadku layout. Niestety tak to wygląda, gdyż próby podpięcia automatycznego wgrywania pliku layoutu poprzez edycję web.xml nie powiodły się. Gdyby ktoś wiedział jak to osiągnąć byłbym wdzięczny. Uruchamiamy aplikację i przechodzimy pod adres http://localhost:8084/index.html i viola – mamy stronkę główną (poniosło mnie trochę przy marketingowych zwrotach, zatem wybaczcie :).

Teraz przyszedł czas na poprawienie naszej strony startowej. Należy przypomnieć, iż określiliśmy kontroler, który jest odpowiedzialny za obsługę żądań do zasobów kończących się na *.html. Jednakże wypadałoby zrobić coś z faktem, iż nasza główna strona będzie wyświetlana również w sytuacji, kiedy w pasku adresu wpiszemy tylko nazwę domeny. Tutaj w przypadku ProgramBash stosowałem zwykły plik HTML z redirectem. Jednakże nie jest to potrzebne. Do pliku web.xml dopisaliśmy regułę, iż wszystkie requesty kończące się na HTML są przechwytywane przez FreeMarkera. W takim razie w katalogu webapp tworzymy PUSTY plik index.html i dopisujemy go do listy plików powitalnych w web.xml

 <welcome-file-list>
        <welcome-file>index.html</welcome-file>
 </welcome-file-list> 

I teraz już bez konieczności zabaw w jakiekolwiek przenoszenie – wszystkie requesty, które pójdą na naszą domenę (jednakże te “całościowe” z prośbą o stronę główną) zostaną obsłużone w ten sam sposób co requesty przychodzące na adres http://domena.pl/index.html. Proste jak konstrukcja gwoździa, szkoda, że dopiero po tym jak się wyczyta o tym u wujka Google. To tyle na dziś – przyznam, że pomijając przygodę z kodowaniem stron w FreeMarkerze i nieudaną próbę podpięcia domyślnego layoutu poznawanie Springa jest całkiem przyjemne. Szybki rzut oka na klasy kontrolerów dostarczane wraz ze Springiem utwierdził mnie w przekonaniu, że ktoś wiedział co robi projektując te narzędzie.

Mavenizacji ciąg dalszy – dlaczego tym razem wyszło

Dziś znów na tapecie Maven. Nie tak dawno pisałem jak poszły moje pierwsze boje z tym narzędziem. W skrócie – nie poszły.

Zakończyłem jednakże prace z szkieletem projektu i po chwili namysłu (plus fakt, że poszedłem spać przed 3) stwierdziłem, że może to i dobrze. Jak wspominałem w poprzednim wpisie w dokumentacji Springa jest opisane tworzenie projektu krok po kroku, wraz z dodawaniem katalogów i takich tam. Stwierdziłem zatem, że jeśli już poznawać nowe narzędzie to od samych podstaw, a do takowych na pewno będzie należało klepanie wszystkiego z palca. Przypomina to trochę poznawanie linuxa od instalowania Gentoo, ale co tam. Utworzony projekt wygląda na razie bardzo skromnie:

Nie ma tego wiele. Podpięte mamy tylko API do serwletów oraz JUnit i to jeszcze nie w wersji 4. Widok w IDE rzecz jasna nie odzwierciedla sytuacji na dysku – tak projekt wygląda od strony plików i katalogów:

Tutaj wiemy już coś więcej. W katalogu src będzie trzymany kod – zarówno ten “podstawowy”, jak i pliki związane z prezentacją w sieci jak np. CSS czy obrazki. Znajdziemy też wstępnie katalog do trzymania testów, a także przygotowany katalog dla plików wygenerowanych i gotowych do wdrożenia na serwerze. Sugeruję zajrzeć do pliku POM.xml, który jest podstawowym plikiem dla Mavena. Na razie jest on dość prosty i krótki:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.wordpress.chlebik</groupId>
 <artifactId>scjpsym</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>scjpsym</name>
 <url>http://maven.apache.org</url>

 <dependencies>

 <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>servlet-api</artifactId>
 <version>2.5</version>
 <scope>provided</scope>
 </dependency>

 <dependency>
 <groupId>javax.servlet.jsp</groupId>
 <artifactId>jsp-api</artifactId>
 <version>2.1</version>
 <scope>provided</scope>
 </dependency>

 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>3.8.1</version>
 <scope>test</scope>
 </dependency>

 </dependencies>
 <build>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-compiler-plugin</artifactId>
 <version>2.0.2</version>
 <configuration>
 <source>1.5</source>
 <target>1.5</target>
 </configuration>
 </plugin>
 </plugins>
 <finalName>scjpsym</finalName>
 </build>
 <properties>
 <netbeans.hint.deploy.server>Tomcat60</netbeans.hint.deploy.server>
 </properties>
</project>

Dość istotna jest ostatnia część pliku, a mianowicie plugin maven-compiler-plugin. Domyśłnie Maven kompiluje kod zgodny z Javą w wersji bodajże 1.3, co jest zasadniczo prehistorią. Dlatego też określenie docelowej wersji na 1.5. Powiedzmy, że na razie taki plik nam starcza. Jednakże aplikacja ma za zadanie działać ze Springiem, Hibernate i Spring MVC. Tutaj dochodzimy do sedna sprawy – zależności. W powyższym przykładzie element dependencies zawiera w sobie opisy pojedynczych bibliotek wraz z ich wersjami. Co więcej – dodanie bibliotek spowoduje przy budowaniu projektu próbę zainstalowania (w sensie dodania do projektu) bibliotek potrzebnych by pracowały te wskazane przez nas. Są to tzw. zależności przechodnie i każdy kto swego czasu pracował z linuxami opartymi na pakietach RPM doceni jak miłą rzeczą jest brak konieczności martwienia się o zależności.

Mała uwaga! Standardowo aplikacje tworzę w środowisku Windows. Zakładam rzecz jasna, że czytelnicy mojego bloga wiedzą, że kiedy napiszę dla przykładu, iż należy wywołać komendę mvn install to albo zrobią to z poziomu konsoli, albo np. Cygwina. O konieczności dopisania lokalizacji plików wykonywalnych Mavena do zmiennych systemowych chyba nie muszę wspominać.

Na początek powiedzmy, że chcemy poprawić naszą wersję JUnita. Trochę nie bardzo wygląda wersja 3.8.1, kiedy kilka tygodni temu wyszła wersja o 1 oczko “wyższa”. Edytujemy zatem plik POM.xml i zmieniamy numerek wersji na 4.8.1. Teraz wystarczy dać PPM na zakładce Test Libraries i wybrać opcję Download missing dependencies. Mamy nowego JUnita.

Zajmiemy się teraz Springiem. Postanowiłem używać wersji 2.5.6, gdyż najnowsza (trzecia) została wydana raptem w lutym bodajże, dlatego też nie jest dla mnie na tyle “wiarygodna” by pisać w niej edukacyjną aplikację (w sensie pierwszej styczności z frameworkiem). Do tego dorzucimy rzecz jasna Spring MVC. Takie zależności dopisujemy do odpowiedniego miejsca w POM.xml.

 <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring</artifactId>
    <version>2.5.6</version>
    <type>jar</type>
    <scope>compile</scope>
 </dependency>

 <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>2.5.6</version>
    <type>jar</type>
    <scope>compile</scope>
 </dependency>

Próba zbudowania projektu w tej chwili po prostu się nie powiedzie. Dlatego choćby, że nasze biblioteki nie zostały bynajmniej ściągnięte. Prawy przycisk myszy na zakładce Libraries i bodajże wybieramy Download source (nie jestem w stanie powtórzyć sytuacji, kiedy nie mam źródeł na kompie, nawet przy nowym projekcie). Jednakże zasadniczo przy dodawaniu zależności należy obserwować widok naszego projektu, gdyż NetBeans wszystko startuje od razu. Grzebiąc dalej trzeba by dodać Hibernate i tutaj zrobimy inaczej. Prawy przycisk myszy na zakładce libraries i wybieramy AddDependency. Pola na górze przeznaczone dla id artefaktu i grupy są podpięte pod autocompleter – zatem spokojnie można wpisać tam org.hi i na liście powinniśmy zostać już tylko z Hibernate. Ostatecznie po dodaniu wpis w pliku konfiguracyjnym wygląda tak:

  <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate</artifactId>
          <version>3.2.6.ga</version>
      </dependency>

Jeśli potencjalnie chcemy używać adnotacji do kontrolowania Hibernate, wówczas trzeba dodać jeszcze taką oto zależność:

 <dependency>
    	<groupId>org.hibernate</groupId>
    	<artifactId>hibernate-annotations</artifactId>
    	<version>3.4.0.GA</version>
    </dependency>

Poprzez dodanie tych dwóch zależności do listy używanych bibliotek zostanie przy okazji dołączony szereg innych. Teraz dla odmiany z konsoli uruchomimy Mavena by pociągnął wszystkie świeże zależności. Polecenie jest proste:

mvn compile

Niestety okazało się, że nie udało się dociągnąć zależności JTA – zrobimy to ręcznie – wchodząc na podaną przez Mavena stronę i ściągając plik JAR na nasz komputer. Potem w konsoli:

mvn install:install-file -DgroupId=javax.transaction -DartifactId=jta -Dversion=1.0.1B -Dpackaging=jar -Dfile=sciezka\do\pliku\jar\wraz\z\nim\samym

No i udało się – plik zainstalowany. Jednakże samo Hibernate to także plik konfiguracyjny. No i tutaj trzeba utworzyć ten plik, a także wskazać go aplikacji. W tym celu w katalogu projektu (konkretnie ścieżka to src/main/resources) tworzymy katalog hibernate i tam wrzucimy nasz plik hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>

    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
    <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
    <property name="hibernate.connection.url">jdbc:postgresql://88.198.31.169/chlebik</property>
    <property name="hibernate.connection.username">moj_tajny_login</property>
    <property name="hibernate.connection.password">moje_tajne_haslo</property>


  </session-factory>
</hibernate-configuration>

I teraz w pliku POM.xml w elemencie build dodajemy taki wpis:

 <resources>
      <resource>
        <directory>src/main/resources/hibernate</directory>
      </resource>
 </resources>

Na sam koniec zaś musimy ściągnąć nasz connector do PostgreSQL. I znów kolejna zależność.

   <dependency>
       <groupId>postgresql</groupId>
       <artifactId>postgresql</artifactId>
       <version>8.3-603.jdbc4</version>
   </dependency>

Ufff, już teraz wiem co to znaczy konfiguracja XMLem. Pozostaje mieć nadzieję, że to wszystko jakoś działa, lub też będzie działać. Nie chciałbym wychodzić za bardzo do przodu i implementować tutaj DAO by sprawdzić czy w ogóle to połączenie działa (mam cichą nadzieję, że tak). Na razie zatem temat zostawiam – kiedy dojdziemy do implementowania logiki biznesowej aplikacji wówczas z całą pewnością zmienię treść wpisu gdyby cosik nie działało jak powinno.

Na sam koniec jeszcze dodatek do konfiguracji Mavena. Otóż podczas budowania projektów dostawałem wciąż komunikat o tym, iż kodowanie projektu to CP-1250 i w związku z tym aplikacja nie będzie przenośna (też nowość). Próby zmiany tego stanu rzeczy w właściwościach projektu nie dawały efektu, dlatego też trzeba było znów odwiedzić plik POM.xml. W sekcji build dorzucamy takie coś:

 <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.4.2</version>
        <configuration>
          <encoding>UTF-8</encoding>
        </configuration>
 </plugin>

I w ten oto sposób po zbudowaniu projektu (no i rzecz jasna ściągnięciu plugina) nasz output radośnie będzie generowany w UTF-8. Jak to w cywilizowanych krajach się dzieje 🙂 To tyle na dziś – w następnym wpisie spróbujemy coś zrobić z widokiem i postawić jakieś bardziej rozbudowane “Hello World”.

Oficjalny nowy projekt – SCJPTester

W ostatnich bojach z Mavenem nie powiedziałem słowa o tym, do czego będzie służyła aplikacja, którą zamierzam tworzyć. Pewnikiem niektórzy domyślili się po nazwie, która przewijała się w screenach z widoku projektu, ale też i na niewiele się to zdało, gdyż ostatecznie nazwę zmieniłem. Panie i Panowie – przed Wami SCJPTester!

Spora część ruchu na blogu jest generowana poprzez zawartość powiązaną z certyfikatem SCJP. Zatem naturalnym rozwinięciem mojego contentu byłoby stworzenie aplikacji, która dałaby możliwość symulacji prawdziwego egzaminu. I taką właśnie funkcjonalność będzie posiadał SCJPTester – napisany z pomocą Mavena, Springa, Springa MVC, a także jakiegoś systemu szablonów integrującego się ze Springiem (nie wybrałem jeszcze żadnego), prace trwają. Zastanawiam się czy nie uderzyć z obsługą frontendu od strony AJAXa i interfejsu w GWT. Kozioł próbował przekonać mnie do Vaadina, że niby lepszy niż GWT, ale moim przekleństwem jest to, iż cały czas “zaliczam” technologie, które są najbardziej popularne i do nich niestety należy GWT, zaś Vaadin nie. Ale to jeszcze pogrzebię, przygoda z Mavenem jeszcze się nie skończyła 🙂

Instalujemy PostgreSQL na Debianie Lenny

Odgrażałem się chyba z 10 razy, że w końcu zainstaluję PostgreSQL, aby podpiąć pod ten system bazodanowy swoje aplikacje. Lata płyną 🙂 zaś PostgreSQL ani widu, ani słychu. Przy okazji tworzeniu nowego projektu i zabaw z Mavenem przyszedł czas i na bazę.

Mój VPS posiada zainstalowanego MySQLa, który służy nie tylko do obsługi moich aplikacji, ale też trzymania wiki, czy Kulturalnego Chlebika. W tym wpisie opiszę jak przebiega instalacja oraz konfiguracja PostgreSQL na serwerze z Debianem Lenny i jak to poskładać do kupy, aby dobrze działało. Wpierw rzecz jasna trzeba odpowiedzieć sobie na pytanie jaką wersję RDBMSa instalujemy. W sumie najbardziej “nową” wersją jest ta oznaczona numerkiem 8.4. Jednakże moja polityka dotycząca nowych wersji jest powszechnie znana, a co więcej, w tym przypadku jest wspierana tym, iż w repozytoriach Debiana znalazłem gotowy pakiet z wersją 8.3. Po części system zadecydował za mnie. Uruchamiamy zatem apta:

sudo apt-get install postgresql-8.3

Apt pomieli swoje i na końcu całego listingu zobaczyłem takie oto dobre rzeczy:

Creating new cluster (configuration: /etc/postgresql/8.3/main, data: /var/lib/postgresql/8.3/main)…
Moving configuration file /var/lib/postgresql/8.3/main/postgresql.conf to /etc/postgresql/8.3/main…
Moving configuration file /var/lib/postgresql/8.3/main/pg_hba.conf to /etc/postgresql/8.3/main…
Moving configuration file /var/lib/postgresql/8.3/main/pg_ident.conf to /etc/postgresql/8.3/main…
Configuring postgresql.conf to use port 5432…
Starting PostgreSQL 8.3 database server: main.

Informacje o utworzeniu nowego klastra plus pojawienie się plików konfiguracyjnych są bardzo dobre – w necie znalazłem informacje, że zdarzały się przypadki ‘niepełnej’ instalacji z paczek, co skutkowało koniecznością dziwnych zabaw z samą bazą i jej skryptami konfiguracyjnymi lub uruchomieniowymi. W moim przypadku jak widać wszystko poszło OK i serwer PostgreSQL został uruchomiony. Wypada przyjrzeć się choć trochę konfiguracji – otwieramy plik postgresql.conf, który znajdziemy w katalogu wskazanym przy instalacji (u mnie jest to /etc/postgresql/8.3/main ). Jest on dość duży i rozbudowany, ale ten wpis nie jest o tuningowaniu PostgreSQL dlatego na razie odpuścimy sobie większość rzeczy poza wartościami zmiennych timezone oraz datastyle. Zgodnie z zaleceniami powinny one wyglądać tak:

datestyle = 'European, German'
timezone = Poland

Choć to w sumie duperel. Istotne jest to, aby móc łączyć się z bazą z dowolnego miejsca. W pliku konfiguracyjnym odnajdujemy zmienną listen_addresses i jeśli jest inaczej to ustawiamy jej wartość na ‘*’ (czyli na wszystkie możliwe interfejsy). Zamykamy plik. PostgreSQL domyślnie tworzy użytkownika o nazwie postgres, ale lepiej zostawić go w spokoju, za to do łączenia się z bazą lepiej stworzyć oddzielnego użytkownika, albo użyć jednego z istniejących – głównie dla bezpieczeństwa (ograniczenie dostępu lub różne prawa). Edycji poddajemy plik ph_hba.conf, który znajduje się tam gdzie główny plik konfiguracyjny. Dopisujemy tam następującą linijkę:

host all chlebik 0.0.0.0 0.0.0.0 password

Co oznacza tyle, że można połączyć się z serwerem bazy danych spoza serwera macierzystego używając do zalogowania użytkownika o nazwie chlebik. Dla łatwości również stworzymy nową bazę danych dla tych połączeń:

su
su postgres
createuser -a -d -P -e -W chlebik
createdb -e -E UTF-8 -O chlebik chlebik

Restartujemy serwer. Teraz wypadałoby sprawdzić czy nasze zabiegi przyniosły jakikolwiek efekt:

su
su postgres
psql template1
\du

I powinniśmy zobaczyć chlebika jako jednego z użytkowników bazy. Skoro tak to pewnie dałoby się zalogować jako chlebik i przy okazji zobaczyć co tam słychać w naszej bazie (pamiętajmy, że utworzyliśmy właśnie nową dla tego użytkownika ).

psql -U chlebik -h localhost chlebik

Logujemy się jako user chlebik do bazy danych o nazwie również ‘chlebik’ znajdującej się na lokalnej maszynie. Zostaniemy poproszeni o hasło. Jeśli wszystko jest OK to zostaniemy zalogowani do konsoli psql-a, gdzie możemy dla przykładu wydać takie polecenie:

\dt

Co powinno doprowadzić do pojawienia się komunikatu No relations found. Trudno by cokolwiek znaleziono – w końcu baza danych jest czysta jak pierwszy śnieg. Jednakże proces logowania przebiegł pomyślnie i wypada się z tego cieszyć. Jednakże to jeszcze nie koniec – połączenie z serwera jest dobre – na pewno nasze aplikacje na nim wdrożone uruchomią się bez problemów. Jednakże ustawialiśmy możliwość łączenia się z bazą spoza serwera. Teraz przetestujemy tę możliwość – ja wybralem do tego program PgAdmin, który mam na dysku, gdyż lokalnie na maszynie developerskiej posiadam zainstalowanego PostgreSQL. Wpisujemy dane i oto mamy: