wtorek, 18 października 2011

Warsjawa 2011 już za nami


W minioną sobotę (15.10.2011) odbyła się Warsjawa 2011. Konferencja ta jest organizowana przez te same osoby co Confitura z tym że ma ona charakter warsztatowy. Ja postanowiłem wziąć udział w ścieżce dotyczącej GWT gdyż ostatnio trochę pokodziłem w tej technologii i chciałem uzupełnić / usystematyzować swoja wiedzę. Ale od początku.

Konferencja rozpoczęła się chwile po 9.00 słowem wstępnym organizatorów. Chwile później poszliśmy już do sal gdzie miały być warsztaty. Sala była trochę mniejsza niż przewidziane 60 uczestników, więc było ciasnawo, ale przyjemnie. No i ilość podłączonych komputerów do sieci elektrycznej musiała się skończyć wysadzeniem korków. Trzeba było kilka przedłużaczy spiąć ze sobą i ukraść prąd z korytarza, aby muc w ogóle rzutnik prowadzącemu  uruchomić. Wysadzenie korków jest rzeczą, której można się spodziewać, ale zbytnio nie ma się jak przed tym zabezpieczyć. No chyba że ktoś ma generator prądotwórczy pod ręką i mógłby udostępnić :P

Warsztaty rozpoczęły się więc o 9.45. Po krótkim wprowadzeniu utworzyliśmy przykładową aplikację i zaczęliśmy zabawę. Niestety prowadzący założył, że będzie Wi-Fi i że będzie działać. Niestety było to błędne założenie, co trochę rozwalało pracę. Przykład ten pokazuje, że przygotowanie prezentacji / warsztatu nie jest sprawą trywialną i że należy się zabezpieczyć na ewentualność braku dostępu do Internetu i wszelkie inne problemy. Całe szczęście pojawiłem się chwilę przed konferencją i zdążyłem jeszcze uruchomić skrypty konfigurujące środowisko, dzięki czemu mogłem wykonywać początkowe ćwiczenia. Poniżej przedstawiam garść interesujących informacji o GWT, które wyniosłem z warsztatu.

Moduł GWT dzieli się na client server i shared. Widać to w nazwach pakietów w naszym module. Klasy umieszczone w pakiecie shared są współdzielone przez client i server. To co jest umieszczone w client i shared jest tłumaczone na JavaScript, więc nie może zawierać / używać tego co nie jest przetłumaczalne na JS. Inaczej dostaniemy błędy kompilacji typu: No source code is available for type <nazwa_klasy> did you forget to inherit a required module?. Trzeba wtedy sprawdzić, czy wskazywana klasa jest osiągalna w client lub shared.

W GWT jest coś takiego ciekawego jak SafeHTML. Chroni on przed atakami Cross-Site-Scripting (XSS). Było tylko o tym wspomniane i z pewnością trzeba kiedyś temat zgłębić.

Inna ciekawostką są klasy rozszerzające SelectionScriptLinker. Definiują one, w jaki sposób ma być generowany kod JS przez kompilator. I tak IFrameLinker generuje kod GWT ładowany w osobne znaczniki <IFRAME>. Inna klasa SingleScriptLinker generuje pojedynczego JavaScript’a, a CrossSiteIframeLinker umożliwia ładowanie skryptów z różnych lokalizacji. To ostatnie przydaje się, gdy deploy’ujemy aplikację na wielu serwerach.

Chcąc skorzystać z wybranego Linker’a musimy dodać odpowiedni wpis w pliku konfiguracyjny modułu (*.gwt.xml). I tak Chcąc skorzystać z CrossSiteIframeLinker dopisujemy:

<add-linker name="xs"/>

Dla SingleScriptLinker jest to:

<add-linker name="sso"/>

Wszystkie linkier’y należą do modułu core w GWT. Chcąc sprawdzić co jest domyślnie włączone i co jeszcze można włączyć, należy poczytać zawartość pliku Core.gwt.xml.

Na warsztacie dowiedziałem się w końcu jak z Developer Mode skorzystać. Wcześniej o nim coś słyszałem ale nie wiedziałem dokładnie jak działa. Najlepiej przygotować sobie projekt z poziomu Eclipse’a: File -> New -> Web Application Project. Dzięki temu mamy możliwość skorzystania z plugin’a GWT do Eclipse’a.



Wybierając opcję GWT Compile Project wtyczka kompiluje aplikację i tworzy konfigurację uruchomieniową dla Eclipse’a. Możemy również sobie wybrać ile kompilator na wypisywać na konsole podczas kompilacji, oraz jak ma wyglądać JS po kompilacji (Pretty, Obfuscated, Detailed)



O dziwo zaimportowanie projektu, utworzonego przez skrypt webAppCreator dostarczany wraz z GWT, nie pozwala nam korzystać z tego dodatku. Po udanej kompilacji możemy uruchamiać naszą aplikację w Development mode.



Wybieramy przeglądarkę i już można się nacieszyć nasza aplikacją. Zaletą jest to, że nie musimy za każdym razem rekompilować całej naszej aplikacji, tylko wciskamy F5 w przeglądarce. Pewnie są jakieś ograniczenia na to, co się automatycznie odświeża a co nie - kwestia dowiedzenia się.

Ciekawą funkcjonalnością jest możliwość logowania na konsolę po stronie klienta. Służy do tego moduł Logging. Aby go uaktywnić, należy w pliku konfiguracyjnym modułu dodać następujący wpis:

<inherits name="com.google.gwt.logging.Logging"/>

Ważne jest aby umieścić go przed naszym Entry Point’em!!! Ja umieściłem za i się męczyłem kilka godzin czemu nie działa.

I już możemy logować:

logger.info("onModuleLoad()");
logger.log(Level.WARNING, "warning");
logger.log(Level.INFO, "info");

Trzeba pamiętać, aby dołączyć standardową bibliotekę javową: java.util.logging.Logger. Efekt widać na konsoli w Eclipse:

Sun Oct 16 19:20:33 CEST 2011 LogowanieEntryPoint
INFO: onModuleLoad()
Sun Oct 16 19:20:33 CEST 2011 LogowanieEntryPoint
WARNING: warning
Sun Oct 16 19:20:33 CEST 2011 LogowanieEntryPoint
INFO: info

Jak i w przeglądarce:



Inną ważna rzeczą jest przyspieszanie kompilacji projektu. Niestety kompilacja do JS trwa długo i dodatkowo jest generowany kod na 6 przeglądarek. Warto dla celów development’u ograniczyć kompilację do jednej przeglądarki. I tak aby generować kod dla Firefox’a należy w pliku konfiguracyjnym moduł dodać następująca linijkę:

<set-property name="user.agent" value="gecko1_8"/>

Warto wiedzieć, że wpisy te są zdefiniowane w UserAgent.gwt.xml.

Tyle mniej więcej było do przerwy obiadowej. Około 13.45 zaczęły przychodzić pierwsze Pizze. Było ich sporo i co jakiś czas dochodziły nowe. Można było się spokojnie najeść, bo pod koniec przerwy widziałem jeszcze niedojedzone kawałki. Jako że przed przerwą budowanie aplikacji nie chciało mi działać, uniemożliwiało mi to aktywne uczestnictwo w warsztatach. Postanowiłem więc (nie ja jeden) przenieść się na ścieżkę wykładową.

Najpierw Koziołek mówił na temat tego jak jeszcze można wykorzystać biblioteki testowe. Otóż ułatwiają one nam budowanie walidatorów danych (np. otrzymanych od klienta). Tutaj Bartek pokazywał jak skorzystać z TestNG.

Inna ciekawostka to zastosowanie Mockito w kodzie produkcyjnym. Da się i jest to przydatne, gdy wiemy, że jakaś funkcjonalność dojdzie w niedalekiej przyszłości, ale jeszcze nie wiemy co to de facto będzie. W tym momencie możemy sobie zbudować interfejs taki, jak będzie nam potrzebny i go zmockować, aby zwracał nam domyślne wartości. Jak już będzie wiadomo co / jak należy to poprawnie zaimplementować, to wyrzucając mocka podpinamy konkretną implementację. Ciekawe rozwiązanie, choć dla niektórych może to być zbyt kontrowersyjne.

Na koniec było jeszcze o DbUnit. Dzięki tej bibliotece możemy zasilać naszą bazę nowymi danymi, np. wraz z kolejnymi release’ami naszej aplikacji. Nie musimy w tym momencie utrzymywać skryptów SQLowych (co jest kosztowne i trudne), a przygotowanie danych można zrzucić na klienta dając mu do ręki Excela.

W ogólności zaletą zastosowania opisywanych bibliotek jest minimalizacja ilości naszego kodu, bo więcej naszego kodu = więcej błędów. Opisywane biblioteki są przetestowane przez duże grono użytkowników, a gdy nasz kod jest mniejszy to łatwiej znaleźć w nim ewentualny błąd. Dodatkowo wykorzystanie TestNG powoduje powstawanie programów samotestujących się.

Na koniec został wykład Jacka Laskowskiego. Jacek opowiadał o TomEE czyli starym Tomcat’ie rozszerzonym o kilka bibliotek (CDI – OpenWebBeans, EJB – OpenEJB, JavaMail, OpenJPA, JSF – MyFaces, JTA - Geronimo Transaction) i certyfikat serwera aplikacji. Czyli mamy nowe narzędzie, które obsługujemy jak stare, a daje nam kilka dodatkowych możliwości. Wcześniej mogliśmy dołączyć dodatkowe moduły ręcznie.

Po omówieniu teoretycznym, Jacek pokazał kilka sztuczek z NetBeans’em i TomEE i jak można szybko wystartować z nowym narzędziem. Niby żaden przełom, ale myślę, że nowy Tomcat pomoże zacząć nowicjuszom współpracę z nim. Sporą cześć tego co była na wykładzie można przeczytać na blogu Jacka, a pewnie jeszcze jakieś uzupełnienia się pojawią. Samo prowadzenie prezentacji jak zwykle na dobrym poziomie.

Na koniec były jeszcze podziękowania dla sponsorów / organizatorów i losowanie nagród. Jak zwykle zostało wylosowane sporo osób, które już poszły do domu. Chyba warto w końcu napisać prostą maszynę losującą, gdyż podobny problem z nagrodami pojawia się na innych konferencjach.

Podsumowując organizacyjnie po za wifi i prądem nie było się do czego czepiać. Pizzy było wystarczająco, napojów troszkę mniej, a i tak super że były. Szkoda trochę, że warsztat z GWT trochę nie wyszedł (problemy z netem i skryptem budującym), ale na szczęście można było alternatywnie pójść na wykłady. No cóż trzeba będzie samemu bardziej usiąść do tej technologii i się pobawić.

niedziela, 25 września 2011

Połączenie Androida z lokalnym servletem


Ostatnio miałem za zadanie skomunikować Androida z własnoręcznie napisanym serwletem. Przykładów w necie można znaleźć pełno, jak się prosto połączyć z Internetem i ściągnąć dowolny dokument czy grafikę. Jest to prosta rzecz o ile pamiętamy o kilku sprawach.

Po pierwsze to należy zmodyfikować nieco plik AndroidMainfest.xml dodając następujący wpis:

<uses-permission android:name="android.permission.INTERNET"/>

Teraz już kod odpowiedzialny za połączone z Internetem powinien już działać. Nie będę go prezentował, bez problemów znajdziecie. Ja tymczasem chciałem się połączyć z własnym Serwletem (osadzonym na Tomcat’cie), uruchomionym na tym samym komputerze co emulator telefonu. No i tutaj zaczęły się schody.

Pierwszy pomysł jaki przychodzi do głowy, to magiczny adres IP: 127.0.0.1. Niestety dla emulatora i telefonu oznacza to tą samą maszynę, czyli emulator / telefon. Po krótkim namyśle skorzystałem z adresu IP mojego komputera. Działa, ale nie byłem z tego zadowolony, gdyż w tym momencie stawało się to nietestowalne, w przypadku uruchomienia na innej maszynie.

Próbowałem również skorzystać z adresu IP routera, który dzieli mi Internet w mieszkaniu. Niby już się tam cos łączył, ale timeout leciał. Prawdopodobnie coś źle skonfigurowałem. Szukając po komunikatach wyjątków, w końcu natrafiłem na super rozwiązanie (niestety piszą ten post nie mogę odnaleźć źródła), na które w życiu bym sam nie wpadł.

Chcąc się połączyć z emulatora Androida na komputer na którym obecnie jest ten emulator uruchomiony, należy skorzystać z IP: 10.0.2.2. Dzięki temu łatwiej odpalić aplikację na innym komputerze. Zastosowanie tego adresu, powoduje że po stronie serwera, będziemy widzieć nasze żądania jako pochodzące z 127.0.0.1. Natomiast żądania wysyłane na adres IP naszego serwera, będą miały źródło takie samo, na którym stoi serwer.

Życzę więc miłego kodowania i bezproblemowych połączeń między emulatorem a testowym serwisem. Mi dojście do tego zjadło sporo czasu.

środa, 15 czerwca 2011

Confitura pełna wiedzy – wrażenia po konferencji

W sobotę 11 czerwca odbyła się w Warszawie największa darmowa konferencja javowa w Polsce: Confitura, zwana wcześniej Javarsovią. Na początku wielkie podziękowania dla organizatorów, wolontariuszy i sponsorów, za chęć organizacji i wsparcia tejże inicjatywy. Ale od początku.

Do Warszawy przybyłem w piątek wieczorem, aby być wypoczętym na konferencji. W sobotę byłem na miejscu o 8.30, szybka rejestracja, obchód po stanowiskach sponsorskich, spotkanie znajomych…

O 9.15 członkowie kapituły oficjalnie rozpoczęli Javarsovie Confiturę. Pierwszy wykładzik był sponsorski na temat KeyNote. Prowadzący mówił bardzo cicho i monotonnym głosem, no ale płaci to niech ma :P Był to dobry czas na rozwiązanie konkursów, przygotowanych przez sponsorów. Pod koniec już wyszedłem i chciałem się napić czegoś. Niestety obsługa cateringowa stała, ale napoje czekały dopiero na przerwę kawową co mnie się niezbyt spodobało.

W tym roku zestaw uczestnika był troszkę uboższy niż rok wcześniej. Zamiast materiałowej i ekologicznej torby (używam do dziś) była papierowa i brakowało mi notesika (na szczęście się przed tym zabezpieczyłem). Nie ma jednak na co narzekać, gdyż konferencja jest w pełni bezpłatna i nie można wymagać nie wiadomo jakich gadżetów. Nie to jest najważniejsze, gdyż nie po gratisy przyjechałem.

O 10.35 zaczęły się pierwsze wykłady. Ja się udałem na Aspekt bezpieczeństwa w tworzeniu aplikacji internetowych Jakuba Koperwasa. Prelegent zaprezentował popularne ataki na aplikacje webowe (jak SQL Injection) jak i mniej popularne (jak CSRF). Wspomniał on również o inicjatywie OSWAP, dzięki której można się pobawić w hakowanie.

Było też o sposobach, jak można się bronić przed różnymi atakami. Przede wszystkim należy nie przestawać myśleć i nie ufać ślepo framework’om. Powinniśmy walidować dane, a nie formularz, gdyż dane do naszej aplikacji mogą spływać różnymi drogami – nie tylko poprzez żądanie http, ale także z innych serwisów, aplikacji, z telefonów... W celu walidacji danych może nam pomóc BeanValidation JSR-303, za pomocą którego można zdefiniować, jakie ograniczenia powinny mieć nasze dane.

Warto również znać różnice pomiędzy używanymi framework’ami i bibliotekami, Przykładowo GWT traktuje tekst jako zwykły tekst, natomiast ExtGWT, jako html. Dzięki temu tworząc przycisk z tekstem <b> text </b> w tym pierwszym dokładnie taki napis zobaczymy na ekranie, a w przypadku ExtGWT dostaniemy przycisk z pogrubionym tekstem.

Kolejnym rodzajem omawianego ataku była kradzież sesji. Można się przed tym bronić, dodając do każdej akcji jednorazowy RequestId, który jest później unieważniany. Można z palca to naklepać, lub jeśli korzystamy z Seam’a, wykorzystać znacznik <s:token>. Można również monitorować czy na pewno uprawniony użytkownik korzysta z danego klucza sesji. Można dodatkowo monitorować MAC i IP, a także używaną przeglądarkę. O ile IP może się czasem zmienić (zależy jakiego mamy dostawcę Internetu), to już zmiana przeglądarki może być podejrzana. Wszystko również zależy od krytyczności naszej aplikacji. Jak by się trzeba było co kilka minut logować na facebook’a, to by ludzie przestali się z niego korzystać. Również warto przesyłać ciasteczka po https. Prelegent na koniec polecał przeczytanie 12 rules for developing more secure Java Code.

Prelegent opowiadał jeszcze o kilku ciekawych rzeczach. Przekazał w ten sposób sporo wiedzy słuchaczom. Może trochę mi brakowało przykładów, ale przy takim czasie prezentacji ciężko je zaprezentować. No i nie było czasu na dogłębne analizowanie omawianych problemów. Prelegent mówił szybko, ale zrozumiale i nie dało się spać. Wykład mi się podobał.

Później była przerwa kawowa. Następnie chciałem iść na Tomasza Skutnika i prezentację: Gdzie jest moja tabela? Czyli jak sobie radzić w Javie i SQL gdy zmienia się schemat bazy danych. Kolega Szymon mnie jednak odwiódł od tego zamiaru i wylądowaliśmy na prezentacji Patrycji Węgrzynowicz, pt. Patterns and Anti-Patterns in Hibernate. Patrycja już kilka krotnie występowała z tą prezentacją na innych konferencjach, w tym na 33deegre i GeeCon’ie. Nawet slajdy zawierały na końcu informacje o pierwszej z wymienionych konferencji.

Prelegentka wzięła na warsztat przykładowa aplikację CaveatEmptor z książki Java Persistence with Hibernate – biblii do Hibernate’a napisanej przez jej twórców. Pokazując kawałek kodu, Patrycja pytała publiczność, czy wiedzą, gdzie jest błąd. Znalazł się ktoś z sali, kto dobrze trafił, co się nie zdarzało na poprzednich wystąpieniach. Jak się okazało, nawet twórcy Hibernate’a mogą się czasem pomylić w pracy ze swoim narzędziem. Z ciekawszych rzeczy, co zapamiętałem, to użycie metody Collections.unmodifableList(), która zwraca jedynie wrappera na oryginalną kolekcję. I w zależności od implementacji getterów i setterów, możemy sobie coś zepsuć. Wykład całkiem, całkiem, tylko te częste eeee… i yyyyyy… Patrycji powodowały, że już się go tak przyjemnie nie słuchało.

Kolejnym wykładem na jaki się udałem, to Jak wycisnąć maksimum z testów? Bartka Majsaka. Było trochę o testach integracyjnych i akceptacyjnych. Prelegent wspominał o takich rozwiązaniach jak Tumbler (wspomaga pisanie w stylu BDD) Cargo (wspomaga konfiguracją i deploy'em w różnych kontenerach) i Arquillian (do testowania kodu osadzonego w kontenerze). Praktyczny przykład z tym ostatnim nie zadziałał, prawdopodobnie z powodu problemów z netem.

Dalej było o Selenium / WebDriver. Bartek testował za jego pomocą funkcjonalność na github'ie. Mianowicie po wciśnięciu T, można wyszukiwać pliki z danego projektu. Istnieje również możliwość eksportu z Selenium do JUnit’a 4, ale to się i tak nie kompiluje i w ogóle nie działa. Można to jednak poprawić (tudzież ręcznie napisać) i wtedy można uruchamiać testy bezpośrednio z ulubionego IDE.

Było jeszcze trochę o BDD i jak można ładnie DSL’e w Groovy’m wykorzystać. Warto również w trakcie build'ów z maszyn wirtualnych korzystać, jeśli musimy przeprowadzać testy w zróżnicowanych środowiskach uruchomieniowych. Prelegent próbował jeszcze coś tam pokazać, za znów nie zadziałało z winy sieci. Spodobała mi się idea nagrywania screencast'ów z testów akceptacyjnych, które to później można wykorzystać, do zbudowania prezentacji pokazującej funkcjonalność produktu.

Następnie był obiad. Tym razem trzeba było sobie za niego zapłacić (nie było tak fajnie jak rok temu) a i tak jakiś wypaśny nie był: zupka, sałatka, kanapka i jabłko. Później był wykład sponsorski, czyli jak zwykle…

Następnie udałem się na Re-fuck-toryzacja czyli sprowadzanie sp****go kodu na właściwe tory Pawła Lipińskiego. Chciał on swoim wystąpieniem udowodnić, że jeszcze potrafi programować… W trakcie prezentacji było krótkie ogłoszenie od organizatorów, że właśnie odholowują źle zaparkowane samochody. Ktoś wybiegł z sali...

Paweł wziął pod lupę open source’owy projekt e-commerce OFBiz Pokazywał w jaki sposób przeprowadzać bezpieczne refaktoryzacje. Da się, nawet bez posiadania testów. Nie odpalał jednak na końcu aplikacji, więc nie wiadomo czy wyszło:P

Trochę czasu zabrakło na pokazanie wszystkiego, a im dalej, tym ciężej było śledzić co się dzieje w kodzie. Na koniec był jeszcze zabawna piosenka o refaktoryzacji przygotowana przez autora.

Kolejną prezentacją, na której byłem, było Zastosowanie przetwarzania asynchronicznego w aplikacjach Tomka Łabuza. Testował on obciążenie aplikacji i pokazywał, jak się ona zachowuje przy przetwarzaniu synchronicznym jaki i asynchronicznym. Prelegent mówił również, kiedy warto zastosować takie rozwiązanie w naszej aplikacji.

Następnie była przerwa kawowa i losowanie nagród od sponsorów. Ja wygrałem otwieracz do piwa z funkcją pendrive’a i 2 bilety do kina. Tak więc można powiedzieć, że losowanie nie było ustawione, ale i tak wolałbym Xbox’a :P

Ostatnią prezentacją w której miałem możliwość uczestnictwa było: Pisz po pijaku, przeglądaj na trzeźwo Piotra Przybylaka. Tu również były nagrody dla aktywnych uczestników, tylko że w postaci piwa lub gorzkiej żołądkowej. W końcu tytuł prezentacji zobowiązuje :)

Prezentacja była o sposobie, w jaki działa nasz mózg i czy da się to jakoś wykorzystać. Można się przełączać pomiędzy rożnymi trybami jego pracy, np. za pomocą alkoholu, spaceru, pisaniu czegoś na kartce zaraz po przebudzeniu… Chcąc wykorzystać dwa tryby pracy mózgu, można stosować pair programing, gdyż wtedy kierowca skupia się na pisaniu linijek kodu, a pilot o tym nie myśli, ale ma za to obraz całości.

Dobre może być również odwrócenie problemu. Chcesz się nauczyć pisać dobry kod? Napisz jak najbardziej brzydki, zagmatwany i niezrozumiały kod. Prelegent wspominał jeszcze o modelu kompetencji braci Dreyfus, Shu Ha Ri, kryzysie pielęgniarek w stanach i o powstawaniu nowych neuronów w mózgu. Podobno szczurom w warunkach laboratoryjnych nowe neurony się nie rodzą (no bo i po co?), ale kto wie jak to w rzeczywistości jest...

Generalnie na wykładzie było sporo śmiechu i sporo braw. Było lekko i przyjemnie. Idealny wykład na końcówkę konferencji. Brawo.

Później było tylko zakończenie konferencji. Podziękowania dla organizatorów, wolontariuszy i sponsorów. Było jeszcze losowanie przygotowanych nagród, ale już na nic się nie załapałem. Liczba osób, które potwierdziły rejestracje to 742, ale wiadomo – ktoś jeszcze nie dojechał, ktoś jeszcze doszedł, wiec trochę ciężko przybliżyć rzeczywistą liczbę uczestników.

Po confiturze udałem się jeszcze pod PKiN na piwko z Szymonem. Ja jeszcze zostałem na niedziele w Warszawie. Wracając pociągiem rozwiązywałem jeszcze jedno zadanie konkursowe firmy OutBox. Musze przyznać, ze bardzo ciekawy konkurs (tzn. treść tego co trzeba zrobić, a właściwie gdzie ją znaleźć). We wtorek było ogłoszenie wyników, ale niestety nic nie wygrałem.

Podsumowując konferencję, to wypadła ona trochę słabiej od zeszłorocznej edycji. Wydaje mi się, że wcześniej wykłady były na trochę wyższym poziomie (albo to ja się czegoś w ciągu roku nauczyłem). Było ciężko się przemieszczać pomiędzy salami (co nie jest dziwne przy tej liczbie uczestników), co skutkowało spóźnieniami na prelekcje. Przerwy mogły by być trochę dłuższe, a napoje dostępne non stop. Więcej niedociągnięć się nie dopatrzyłem i za rok będę starał się znów wziąć udział w tej konferencji.

wtorek, 7 czerwca 2011

Zmiana nazwy pakietu w projekcie Android'owym w IDEA

W jednym z ostatnich wpisów: Inne podejście do przechowywania danych w systemie Android, z wykorzystaniem db4o i NetBeans 6.9 wspominałem o użyciu IntelliJ IDEA w celu sprawdzenia jak sobie radzi z aplikacjami android’owymi. I rzeczywiście wsparcie jest lepsze. Póki co to natrafiłem tylko na dziwne zachowanie jeśli chodzi o zmianę nazwy pakietu. Mianowicie po wybraniu pakietu i Refactor -> Rename (Shift + F6) wyskakuje mi poniższy monit:



Z początku trochę mnie zdziwił komunikat. Patrząc tylko na przedostatnią linię, nie rozumiałem intencji. Przecież pakiet jest utożsamiany z katalogiem, więc o co chodzi? Bliższe wczytanie się w komunikat, już wyjaśnia co się dzieje. Otóż IDEA umieszcza pliki automatycznie generowane (takie jak klasa R) w osobnym katalogu (/gen). Niezależnie od wybranej opcji (po za Cancel oczywiście) zmieniana jest nazwa katalogu zawierającego nasze pliki źródłowe. Przy wyborze Rename package, dodatkowo zostanie zmieniona nazwa podkatalogu /gen, gdzie są generowane automatycznie pliki projektu (np. klasa R).

Teraz przy próbie uruchomienia (Shift + F10) aplikacji wyskakuje okienko do edycji konfiguracji.



Możemy w tym momencie olać ten ekran i samemu poprawić ścieżki do naszych aktywności w pliku AndroidManifest.xml. Całe szczęście, że IDEA podświetla na czerwono błędne klasy, umieszczone w plikach XML-owych. O takiej funkcjonalności w NetBeans’ie można tylko pomarzyć.

Kilkakrotne próby powtórzenia tej czynności, uświadomiły mi, że środowisko nie zawsze tak samo wszystko modyfikuje. Raz musiałem w jakimś pliku konfiguracyjnym coś grzebać, a ostatnio nawet udało się odpalić od razu aplikację. Czyżby to było adaptacyjne środowisko programistyczne? Jeśli tak to jestem pod wrażeniem.

sobota, 28 maja 2011

Podświetlanie wystąpień zmiennych w kodzie w Eclipse

Jakiś czas temu mój Eclipse zwariował i nie chciał podświetlać wszystkich wystąpień zmiennych w kodzie Javy, gdy na jakiejś zmiennej był ustawiony kursor. Moja praca stała się bardziej uciążliwa, gdyż trudniej mi było przeczytać / zrozumieć nie swój kod.

Jako że nie znam dokładnie środowiska, chwilę się naszukałem co może być nie tak. Wszystko można zmienić w menu Window -> Preferences -> Java -> Editor -> Mark Occurrences.



Warto mieć tu wszystko włączone, aby widzieć co gdzie w kodzie występuje. Przykład poniżej:



Kursora bezpośrednio nie widać, ale proszę mi wierzyć, że jest on ustawiony na obiekt separator w linii 14. Dzięki temu w linii 16 widzimy podświetlenie tej samej zmiennej.

Podsumowując powiem jeszcze, ze pisząc ten post zrozumiałem, dlaczego w pewnym momencie to podświetlanie mi zniknęło. Otóż chcą sobie przypomnieć skrót klawiaturowy do wyświetlania Outline’a aktualnej klasy w oknie z kodem, omyłkowo wcisnąłem Alt + Shift + O, co jak się okazało wyłącza podświetlanie tych zmiennych. Natomiast skrót do wyświetlania Outline’a klasy (czyli zawartości) to Ctrl + O. Podwójne wciśnięcie tej kombinacji, to wyświetlenie całej zawartości klasy, wraz z klasami bazowymi.

Tyle na dziś.

Żródło:
Eclipse: Mark Occurrences for Quick Visual Help

poniedziałek, 16 maja 2011

Wrażenia po konferencji GeeCON cz.2 (Conference Day II i Community Day)

Wrażenia z pierwszego dnia konferencji opisałem już w poprzednim wpisie: Wrażenia po konferencji GeeCON: Conference Day I. W piątek (Conference Day II) jakoś ciężko mi było się wcześnie rano zebrać. Jako że znów początkowo musiałem być na stoisku firmowym, nie uczestniczyłem w porannych wykładach.

Pierwszy wykład na który dotarłem to była prelekcja: Eugene’a Ciurana The No-Nonsense Guide to Hadoop and HBase in Enterprise Apps. Autor opowiadał o framework’u Hadoop, który skupia w sobie sporo innych ciekawych technologii, wspomagających rozproszenie systemu. Było dużo wiadomości, ale bez konkretów. Trochę dokładniej było o bazie HBase podobnej do BigTable od Google. Na koniec prelegent namawiał do pracy w swojej firmie i sporo oferował, za polecenie pracownika.

Później był obiad, dokładnie taki jak wczoraj. Część uczestników zamiast niego poszła gdzieś indziej zjeść.

Następnie udałem się na prezentację Marka Matczaka pt. 10 common pitfalls when using Hibernate, z którym mam przyjemność współpracować. Słyszałem również tą prezentację kilka dni wcześniej i dokładnie wiedziałem o czym będzie. Marek pokazał pułapki na jakie można się natknąć używając Hibernate’a. Ciekawa prezentacja poparta przykładami z życia. Po prelekcji grupka ludzi otoczyła Marka, zasypując go pytaniami. Sporo ludzi nie zrozumiało idei session-per-conversation, czyli wzorca przydającego się w aplikacjach, gdzie mamy kilka kroków w jakimś procesie, jak np. bookowanie biletów lotniczych. Warto wówczas zacząć sesję Hibernate’ową na początku procesu rezerwacji biletu, a zakończyć ją, gdy już będzie zapłacone. Rozwiązanie takie jest zaimplementowane we framework'u Seam.

Następnie poszedłem na Anton’a Arhipov’a Bytecode for discriminating developers. Początkowo było o drzewach AST, czyli krótkie wprowadzenie do kompilatorów. Muszę przyznać że slajdy były bardzo ładnie przygotowane, zwłaszcza te pokazujące operacje wykonujące się na stosie. W ogólności jest 256 słów kluczowych w maszynie wirtualnej Javy, i praca z bytecode’m nie jest taka straszna dzięki narzędziom javap (do podejrzenia kodu JVM) i Javassist (do modyfikowania kodu w locie). Później trochę przysnąłem i obudziłem się pod koniec. Anton jest współautorem narzędzia JRebel, służącego do szybkiego redeploy’a naszych aplikacji, bez konieczności restartowania serwera. Szkoda, że rozwiązanie jest płatne:/

Następnie wybór prezentacji był bardzo ciężki i w końcu poszedłem na Andres’a Almiray’ego z prezentacją Polyglot Programming. Prelegent porównywał jave, groovy’ego, scalę, i clojure. Mi to trochę przypominało onanizm składniowy. Może przykłady były źle dobrane do tego, aby pokazać przewagę pewnych języków nad innymi? Później autor pokazał, że można łączyć te języki ze sobą.

Na koniec poszedłem jeszcze na prezentację dra Jim’a Webber’a pt. A programmatic introduction to Neo4j. Prześmieszny koleś i na scenie robił niezłe show. Biegał, rzucał żartami i cieszył się jak publiczność atakowała go pytaniami. Co do wykładu, to najpierw ogółem opowiadał o NoSQL, że coraz więcej danych przechowujemy i że są one coraz bardziej skomplikowane. Najpierw kilka godzin modelujemy nasze dane, rozpisujemy relacje, tworzymy bazę danych, a na koniec i tak robimy denormalizację, bo nasza baza nie wyrabia. Jim podał dobre przykłady, gdzie można wykorzystać bazy grafowe. Porównał szybkość wyszukiwania naszych przyjaciół w typowym serwisie społecznościowym. Przewaga Neo4j w stosunku do relacyjnej bazy danych była tutaj miażdżąca. Jim polecał ściągnięcie tutoriala o Neo4j z github’a: https://github.com/jimwebber/neo4j-tutorial.

Dodatkowo dostęp do Neo4j z poziomu innych języków, może łatwo się odbywać przez REST’a. Jeśli chodzi o poziom rozdzielenia transakcji w Neo4j to jest to dostęp serializowany, ale na używanym podgrafie. Bardzo fajna prezentacja, szkoda, że dopiero na koniec konferencji.

Gdzieś tam w międzyczasie było jeszcze losowanie książek i innych nagród na stoiskach sponsorskich, ale na nic się nie załapałem.

Zostałem jeszcze w Krakowie na sobotę na Community Day. Tam już organizatorzy byli kompletnie wyluzowani, gdyż odbywało się to w pobliskim hotelu i było o wiele mniej uczestników (większość w piątek wieczorem pojechała do domu).

Na Community Day najpierw uczestniczyłem w Visage Android Hands-on Lab, prowadzonym przez Stephen’a Chin’a. Przedstawiał on coś co się nazywa Visage i służy do budowania GUI w JavaFX m.in. na Androida. Niby mniej tekstu i przyjemniejszy w czytaniu niż XML, ale jakoś nie do końca się przekonałem. Prezentacja była trochę niedopracowana i właściwie pomagaliśmy Stephan’owi ją usprawnić.

Autor przygotował obraz wirtualnej maszyny z kompletnym środowiskiem. Pomysł dobry, ale wykonanie trochę słabe. Początkowo dużo grzebaliśmy w podstawowym edytorze tekstu, dodając nowe funkcjonalności do naszej aplikacji. Wiązało się to ze zgadywaniem, w którym pakiecie może leżeć dana klasa. Później kopiowaliśmy pliki do świeżego projektu, modyfikowaliśmy XML’e, po to aby móc w końcu uruchomić całe cudo w NetBeans’ie (akurat był zainstalowany na wirtualnym obrazie). Ze względu na różne problemy uczestników po drodze, nie udało nam się zrealizować całości.

Po „laborce” był obiad. I tu o dziwo był obiad hotelowy, smaczny i całkiem spory wybór. Kto chciał mógł również sobie zamówić piwko.

Po obiedzie poszedłem jeszcze na prezentacje Tomasza Kaczanowskiego, pt. Who watches the watchmen? - on quality of tests. Właściwie jakieś 85% omawianych zagadnień już gdzieś wcześniej słyszałem i wiele nowego się nie nauczyłem. Mimo wszystko prezentacja była fajna z dobrym angielskim prelegenta i kameralnym gronem słuchaczy.

Tego dnia jeszcze dostałem od kolegi Krzyśka fajną nalepkę na klawiaturę, ze skrótami do IntelliJ IDEA. Podobno rozdawali to dzień wcześniej na jakimś wykładzie, ale mnie to ominęło. Jak wygląda taka klawiatura (i nalepki) można zobaczyć na blogu Hamlet’a D'Arcy.Tak samo okleję swoją klawiaturę w laptopie:) Przydało by się jeszcze coś takiego dla Eclipse’a.

Podsumowując uważam konferencję za udaną. Jedynie trochę obiad był kiepski, ale poziom prezentacji był wysoki. Wiadomo, że czasem się trafiło tak, że nie bardzo było na co iść, no ale trudno. Niemal na każdej konferencji się tak zdarza. Teraz zostaje czekać na publikacje prezentacji i nagrywanych filmów z wystąpień. Za rok trzeba się znów tam pojawić.

A już niedługo: Confitura (dawniej Javarsovia). Obecnie trwają prace na wyborem tematów, ale już wkrótce powinna ruszyć rejestracja uczestników. Już się nie mogę doczekać.

Wrażenia po konferencji GeeCON: Conference Day I

Dzięki uprzejmości mojego aktualnego pracodawcy, firmy Capgemini  mogłem wziąć udział w konferencji GeeCON. Co prawda musiałem przez część czasu stać na stanowisku sponsorskim, ale i tak sporo skorzystałem z wykładów. Zacznijmy od początku.

Do Krakowa przyjechałem razem z kolegą z pracy w środę wieczorem. Po zameldowaniu się w hotelu i chwili odpoczynku, poszliśmy zobaczyć kino, w którym miała się odbywać konferencja. Część stanowisk sponsorskich była już rozłożona, a że było już późno, postanowiliśmy się rozłożyć następnego dnia z samego rana. Pojechałem jeszcze się spotkać z ziomkiem z rodzinnego miasta i do hotelu wróciłem około północy. Poprosiłem jeszcze w hotelu o żelazko i deskę do prasowania, ale się nie doczekałem :/

W czwartek wstałem około 5.40, aby móc pójść jak najwcześniej na miejsce konferencji i rozłożyć stanowisko sponsorskie. Na miejscu byliśmy chwilę po 6 i dobrą godzinkę zajęło nam składanie całości. Później jeszcze powrót do Hotelu na śniadanko i z powrotem na konferencję.

Chwilę po 8.00 zaczęli się schodzić pierwsi uczestnicy. Dla każdego uczestnika był zestaw: duża ekologiczna torba, koszulka i kubek. Bardzo podobała mi się ulotka IntelliJ IDEA, na której były wypisane skróty klawiaturowe. Fajna pomoc na początek nauki nowego środowiska. Trzeba powiesić w widocznym miejscu i często zerkać. Ponadto był jeszcze program z opisem konferencyjnych wykładów, gazetka Open Source Journal i trochę spamu.

Z początku konferencji stałem na stoisku sponsorskim, a pierwszy wykład na który dotarłem to była prelekcja: Dra Heinz’a Kabutz’a pt. Reflection Madness. Autor jest jednym z redaktorów serwisu javaspecialists.eu. Było to szczególnie widać po formatce prezentacji i sporej liczbie odwołań do artykułów w tym serwisie. Generalnie sporo prelegentów nie trzymało sie standardowej formatki, co mi się nie podobało.

Co do samej prezentacji to było dużo o mechanizmie refleksji w Javie. Początkowe możliwości które autor pokazywał były mi znane, gdyż używałem je intensywnie w pracy magisterskiej. Późniejsze przykłady były jednak bardziej zaawansowane i dzięki temu mechanizmowi można wszystko zrobić, na co domyślnie kompilator Javy nam nie pozwala. Nie jest to mechanizm, który się wykorzystuje w codziennej pracy, ale znajomość tego się przydaje. Końcowa konkluzja jest taka, że warto stosować SecurityManager w miejscach narażonych na hakowanie naszego kodu. No i w wolnym czasie trzeba będzie przejrzeć posty publikowane na javaspecialists.eu.

Po wykładzie był obiad. Nie był on rewelacyjny: ryż z kawałkami mięsa i sos. Do tego nie było gdzie usiąść, no ale trudno. Kino nie było w całości wynajęte (jedynie 3 sale i hol), więc nawet organizacyjnie było by to trudne. Organizatorzy poszli trochę po kosztach, ale miejsce konferencji rekompensuje to niedociągnięcie. Możliwość oglądania prezentacji na ekranie kinowym, z porządnym nagłośnieniem i wygodnymi fotelami sprawia, że nawet w ostatnim rzędzie można w pełni skorzystać z konferencji.

Po obiedzie udałem się na prezentację Michaël’a Figuière’a i Cyrille’a Le Clerc’a pt. NoSQL & DataGrid from a Developer Perspective. Panowie byli przedstawicielami firmy Xebia i pochodzili z Francji. Gdybym wcześniej zwrócił na to uwagę, to bym się zastanowił, czy iść na ten wykład. Słuchanie francuskiego angielskiego nie jest łatwe, ani przyjemne. Prelegenci pokazywali dużo obrazków i wiedzy, ale bez konkretów, reklamując na końcu swoją firmę. Fajnie, że pokazali podejście do transakcji w rozwiązaniach NoSQL. Mianowicie można dodać obiektom metody typu DO i UNDO. Przykładowo jeśli mamy koszyk internetowy na sprzedawane produkty i ograniczoną ilość produktów, to jedna metoda wkłada do koszyka towar, zmniejszając liczbę dostępnych produktów w bazie danych, a druga cofa tą operację. Gdy dojdzie do realizacji zamówienia i się okaże, że któryś z produktów jest niedostępny i gdy użytkownik wycofa się z zakupów, to dla dostępnych produktów wywołujemy metodę typu UNDO. A wszystko odbywa się bez transakcji. Dodatkowo mieli fajny styl rysunków, z taką kreską, jakby malowaną grubym ołówkiem lub kredką świecową.

Podczas całej konferencji brakowało mi pani z dzwoneczkiem, informującej o rozpoczęciu wykładów. Widziałem takie rozwiązanie na którejś z poprzednich konferencji i było ono bardzo praktyczne. Brak „naganiacza / przypominacza” powodował, że się prelekcje ciągle opóźniały i przeciągały. Przerwy jednak miały sporo zapasu czasowego i pozwalały / dopuszczały takie sytuacje.

Kolejną prezentacją, którą odwiedziłem, było drugie wystąpienie dra Heinz'a Kabutz'a pt.
Productive Coder. Szkoda, że prelegent nie wyświetlał na ekranie skrótów klawiaturowych z których korzysta. Używał on środowiska IntelliJ IDEA. Co mi się spodobało, to równoczesne dodawanie kilku polom w klasie tego samego zakresu, wyświetlanie linii w IDE oddzielających kolejne metody, hotkey do przejścia w tryb pełnego okna… Musze poszukać, jakie to są skróty. Prezenter twierdził, ze powinniśmy poświęcić 10 godzin na poznawanie hotkey’ów w naszym środowisku programistycznym. Całkowicie się zgadzam. Uważam, że warto tu zastosować programowanie w parach i oglądanie screencast'ów lub pracy innych programistów.

Później Heinz pytał się publiczności o to, czy obiekt typu String jest mutable czy immutable. My programiści de facto z niego korzystamy jako immutable, ale w rzeczywiśtości jest mutable, czyli modyfikowalny. Ilustruje to poniższy kod:

String myText = "My Example String";
Set<String> mySet = new HashSet<String>();
mySet.add(myText);
System.out.println(myText);

Gdy ustawimy breakpointa na trzeciej linii to zobaczymy, że wewnętrzne pole hash w obiekcie myText ma wartość 0. Po wykonaniu 3ciej linii zmieni się ono na inną wartość. Obiekt zmienia więc swój stan. Skąd sie to bierze? Mianowicie podczas dodawania tekstu do zbioru, wywoływana jest metoda hashCode() na obiekcie myText i obliczana jest wartość hash’a. Żeby nie obliczać jej wielokrotnie, to jest ona zapamiętywana do późniejszego użycia. Jako, że obiekty typu String są używane zazwyczaj w kontekście, gdzie wartość ta nie ma znaczenia, to nie jest ona obliczana w trakcie tworzenia obiektu – wiadomo wydajność.

Doktor zachęcał również do wykorzystywania inspekcji kodu dostępnych w IntelliJ IDEA (menu Analyze -> Inspect Code...). Narzędzie potrafi między innymi wyszukać pola, które mogą mieć mniejszy zakres widoczności, pola które można zmienić na finalne, lub są niezainicjowane itd. Generalnie to potężne narzędzie do statycznej analizy kodu, które od razu potrafi wprowadzić poprawki do projektu. Szczególnie warto je wykorzystać, przy otrzymaniu odziedziczonego kodu po kimś. Dzięki niemu można znacząco pozbyć się nieużywanego kodu, który zaśmieca cały projekt.

Prelegent pokazywał jeszcze ciekawe komentarze w kodzie SDK, które nic nie wnoszą i jak się zmieniają w kolejnych wersjach SDK. Proponował on wyłączyć wszelkie automatyczne generowanie komentarzy, gdyż to nic nie daje. Nawiązała się dyskusja ze słuchaczami, czy warto stosować komentarze czy nie. Publiczność twierdziła, że należy pisać kod tak, aby był zrozumiały sam przez siebie. Heinz twierdził jednak, że kod mówi jak, a komentarz dlaczego tak a nie inaczej. Pokrywa się to z informacjami, które ostatnio przeczytałem w książce: Kod doskonały Steve’a McConnell’a. Ponadto jak nie jesteśmy w stanie napisać dobrego komentarza, to oznacza to, że sami nie wiemy jak nasz kod funkcjonuje i powinniśmy go poprawić.

Później miałem iść na prezentację Hamlet’a D'Arcy’ego  pt. New Ideas for Old Code, ale jakoś długo się zbierałem i w końcu nie doszedłem, czego później żałowałem.

Następnie chciałem iść na Aslak’ena Knutsen’a na prezentację Arquillian: Real Java enterprise testing, ale gdy się dowiedziałem, że chodzi o testowanie EJB z całym kontekstem kontenera, to sobie dałem spokój. Staram się trzymać od takich ciężkich rzeczy z daleka. Ostatecznie poszedłem więc na Nicolas’a Leroux’a, Morten’a Kjetland’a: Play! framework: a revolution in the Java world. I znów Francuzi. Co prawda jeden miał dobry angielski, ale mało mówił, gdyż stał obok, lub kodował na żywo, a drugi opowiadał, co ten pierwszy pisze. Szkoda tylko, że nie korzystał ze skrótów klawiaturowych, tylko właściwie wszystko pisał ręcznie, prawie jak w notatniku. Generalnie fajny pomysł na prezentację – jeden koduje, a drugi mówi o co chodzi.

Prelegenci to autorzy przedstawianego framework’a. Fajnie, że nie trzeba kompilować całego kodu po wprowadzeniu małej zmiany, tylko wystarczy odświeżyć stronę w przeglądarce. Ciekawe jak to we wnętrzu jest zorganizowane? I jak coś się sypnie, to bezpośrednio w przeglądarce widzimy w której linii kodu i co w niej jest! Prelegenci napisali na szybko czat przez przeglądarkę i pozwolili publiczności się połączyć i popisać. Po kilku testowych wpisach zaczęły się zgodnie z moimi przewidywaniami „ciekawsze” wpisy, typu: „Euro 2012 w Łodzi”. Na koniec ktoś jeszcze napisał Cross-site scripting i wyświetlił komunikat na ekranie, ukazując słabość framework’a. Podobno w Lift’cie jest to wbudowane we framework.

I to był ostatni wykład pierwszego dnia konferencji. Wieczorem jeszcze byłem na imprezie konferencyjnej w klubie Pauza na Florianskiej. Można było tam pogadać z innymi uczestnikami, wypić piwko i powymieniać się spostrzeżeniami. Wiadomo, że nie można było poszaleć, gdyż jeszcze czekał nas drugi dzień konferencji, o którym w kolejnym wpisie.

sobota, 7 maja 2011

Inne podejście do przechowywania danych w systemie Android, z wykorzystaniem db4o i NetBeans 6.9

W systemie Android domyślnie mamy dostęp do relacyjnej bazy danych SQLite w której możemy zapisywać informacje z naszej aplikacji. Jest to typowy sposób dostępu do danych w tym systemie. Nie jest dziwne, że do tego systemu została wybrana ta baza. Nie posiada ona wielu magicznych dodatków (jak obecnie popularne kombajny) i założenia jest „Lite” (przynajmniej z nazwy). Z innej strony jest to baza o ciekawym stosunku kodu źródłowego do testów. Odsyłam do artykułu: Extremalne testowanie w SQLite Pawła Lipińskiego. Jak skorzystać z tej bazy jest już opisane na blogu Mirosława Stanka (część 1, część 2, część 3) jak i na helloandroid.  Ja nie będę po raz kolejny opisywał tego rozwiązania, ale postaram się poniżej pokazać inne (ciekawsze?) podejście do tematu, z wykorzystaniem obiektowej bazy danych.

DataBase For Objects, zwana powszechnie db4o, to interesująca alternatywa dla SQLite w systemie Android, jeśli chodzi o składowanie danych. Od wersji 7.5 biblioteka daje wsparcie dla tej platformy. Poniżej przedstawię jak zbudować projekt w NetBeans’ie 6.9 z wykorzystaniem tej biblioteki.

Tworzymy w NetBeans’ie nowy projekt typu AndroidApplication. Następnie do bibliotek dodajemy JAR’a zawierającego db4o.


Następnie warto skorzystać z klasy Db4oHelper przedstawionej przez Damasia Maneiro (niestety nie mam pojęcia jak to po polsku odmienić) w artykule na dzone.com: Using db4o in an Android application. Jest tam sporo kodu odwołującego się do klas z tamtejszego projektu, więc pozwoliłem sobie trochę ten kod zmienić do naszych potrzeb. Listing poniżej.

public class Db4oHelper {

    private static ObjectContainer oc = null;
    private Context context;

    public Db4oHelper(Context ctx) {
        context = ctx;
    }

    public ObjectContainer db() {
        try {
            if (oc == null || oc.ext().isClosed()) {
                oc = Db4oEmbedded.openFile(dbConfig(), 
                        db4oDBFullPath(context));
            }
            return oc;
        } catch (Exception ie) {
            Log.e(Db4oHelper.class.getName(), ie.toString());
            return null;
        }
    }

    private EmbeddedConfiguration dbConfig() throws IOException {
        EmbeddedConfiguration configuration = 
                Db4oEmbedded.newConfiguration();
        return configuration;
    }

    private String db4oDBFullPath(Context ctx) {
        return ctx.getDir("data", 0) + "/" + "database.db4o";
    }

    public void close() {
        if (oc != null) {
            oc.close();
        }
    }
}

Mamy do dyspozycji publiczny konstruktor, który jako argument przyjmuje Context – podobnie jak w SQLite. Potrzebne nam to będzie do umieszczenia pliku z bazą danych w miejscu, gdzie znajdują się dane aplikacji. Następnie mamy metodę db(), która zwraca nam instancję klasy odpowiedzialnej za połączenie z bazą. Mamy jeszcze metodę zwracającą nam konfigurację bazy (domyślna nam początkowo wystarczy) i ścieżkę do pliku z bazą. Na koniec metoda do zamknięcia połączenia z bazą.

Teraz można już napisać klasy, które chcemy składować w bazie danych. Mamy kilka możliwości jak to zrobić. Ja poniżej przedstawię prosty obiekt POJO i odpowiadającą mu klasę DAO. Można oczywiście to wszystko w jedną klasę wrzucić, ale tak będzie ładniej i poprawniej. Poniżej przykładowy kod klasy User.

public class User {

    private String login;
    private String password;

    public User(String login, String password) {
        this.login = login;
        this.password = password;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

W klasie są definiowane 2 pola typu String o nazwach login i password oraz odpowiadające im gettery i settery. No i jeszcze konstruktor przyjmujący te parametry. Jeśli ktoś woli programować w stylu funkcyjnym, to można zrobić pola final i wyrzucić settery. Db4o i tak zadziała, gdyż do ustawiania wartości wykorzystuje refleksje do pól składowych, a nie do setterów.

Proszę zwrócić uwagę, że klasa nie posiada żadnego pola w stylu ID. Dodawanie do klas persystentnych identyfikatorów, to niemalże konieczność w świecie relacyjnym, gdyż dzięki identyfikatorom tworzy się relacje i złączenia przy zapytaniach. W bazach obiektowych tego nie potrzebujemy! Mamy przecież referencje i kolekcje.

Poniżej kod klasy DAO dla klasy User:

public class UserDao {

    private ObjectContainer db;

    public UserDao(Context context) {
        Db4oHelper db4oHelper = new Db4oHelper(context);
        this.db = db4oHelper.db();
    }

    public void saveOrUpdate(User user) {
        db.store(user);
    }

    public void delete(User user) {
        db.delete(user);
    }

    public List<User> getAll() {
        return db.query(User.class);
    }
    
    public List<User> getByLogin(String login) {
        User example = new User(login, null);
        return db.queryByExample(example);
    }

    public List<User> getByLoginAndPassword(
                 String login, String password) {
        User example = new User(login, password);
        return db.queryByExample(example);
    }
}


Klasa posiada konstruktor, za pomocą którego do klasy przekazujemy obiekt typu Context. Jest to klasa android’owa, za pomocą której Db4oHelper może się dostać do odpowiedniego miejsca na zapisanie pliku z bazą. Następnie pobieramy i zapamiętujemy obiekt typu ObjectContainer pochodzący z biblioteki db4o i za jego pomocą odbywa się dostęp do danych. Dalej mamy operacje tworzenia, modyfikacji, usuwania i pobierania wszystkich obiektów - nic specjalnego, ot proste wywołanie pojedynczych metod.

Trochę (ale tylko troszkę) ciekawsza jest metoda getByLogin(), która korzysta z query by example. W skrócie, ta metoda wykonywania zapytań, polega na utworzeniu najpierw obiektu, który będzie przykładem, a następnie wywołaniu odpowiedniej metody zwracającej wszystko, co do danego wzrorca pasuje. Domyślne wartości pól klasy są dopasowywane dowolnie, a te zmodyfikowane dokładnie. W tym przypadku zostaną zwrócone obiekty posiadające ustawione pole login na takie samo jak przekazane w argumencie metody. No prościej się chyba nie da. Istnieją w db4o jeszcze inne bardziej wyrafinowane metody zapytań, ale to nie temat na ten wpis.

Ludzie doświadczeniem z dużymi systemami i relacyjnymi bazami danych, widząc powyższy kod, zaraz zaczną krzyczeć: „a co z dostępem równoległym?”, „a gdzie początek i koniec transakcji?”, itd. Otóż w ogólności db4o wspiera ACID, a poziom izolacji transakcji ma ustawiony na Read Committed. Pytanie z mojej strony: czy rzeczywiście wszędzie tego potrzebujemy? Z tego, co mi wiadomo, to zdarzenia z aktywności w Androidzie są obsługiwane synchronicznie, tzn. w tym samym wątku co GUI. Jeśli nie tworzymy dodatkowych wątków do obsługi zdarzeń (ze względu na ich banalność i szybkość), to nie potrzebujemy transakcji.

Dobra, to teraz by się przydało jakieś GUI dorobić, aby można było zobaczyć jakiekolwiek efekty działania. Po uruchomieniu aplikacji będą się pojawiać dwa przyciski: Create New User i Login. Te będą kierować już do następnych ekranów. Tam będzie można utworzyć nowego użytkownika (i oczywiście go zapisać w bazie), albo się zalogować do aplikacji (na podstawie loginu i hasła zapisanego w bazie). Nie pokazuję tutaj jak utworzyć GUI, gdyż nie jest to tematem tego artykułu. Całkowity kod zamieszczam na końcu wpisu.

Przy pierwszej próbie uruchomienia tak skonstruowanej aplikacji dostaniemy błąd. Jeżeli nie zepsuliśmy niczego po drodze to problem jest jasny. Samo dołączenie biblioteki db4o do projektu nie spowoduje jej dołączenia w trakcie budowy projektu. Należy jeszcze dodać do build.xml następujący target (lub podobny):


    
        
    


Uważam, że środowisko programistyczne powinno być na tyle inteligentne, aby się troszczyło za nas takimi detalami. No ale cóż, nie można mieć wszystkiego. Teraz już powinno pójść gładko i jeśli nic nie popsuliśmy w XML’ach to powinniśmy zobaczyć naszą aplikację. Przykładowe screeny poniżej:



Pod koniec chcę zaznaczyć, ze NetBeans 6.9 nie jest idealnym środowiskiem do pisania aplikacji androidowych (może trzeba jeszcze poczekać?). W trakcie pracy nad projektem natrafiłem na sporo utrudnień. Przykładowo, podczas refaktoringu, po przeniesieniu klasy aktywności, aplikacja przestawała działać. Trzeba było wówczas w AndroidManifest.xml trochę pogrzebać i poprawić nazwy klas. Również zmiana nazwy pakietu wymuszała dodatkowe grzebanie w project.properties.

Z ciekawości sprawdziłem jeszcze jak sobie ze wsparciem Androida radzi IntelliJ IDEA (tak w końcu ją zainstalowałem :) ). Tutaj przeniesienie klasy do innego pakietu nie stanowi problemu. Podobnie z dodaniem biblioteki db4o do projektu. Co do zmiany nazwy pakietu to napiszę o tym w następnym poście (aby wszystko na raz nie było w jednym). Dodatkowo Idea od razu pokazuje Log konsolę z Androida. Chcą ją aktywować w NetBeans'ie trzeba kliknąć: Window -> Output -> ADB Log.

Jeszcze w między czasie tworzenia tego wpisu (nie powstał on w jeden dzień) pojawił się NetBeans 7.0. Tam jednak nawet nie mogłem dodać żadnej zewnętrznej biblioteki do projektu android'owego, więc ewentualna migracja do nowego środowiska musi poczekać.

Link do kodu:

db4oOnAndroid.zip

git://github.com/mstachniuk/db4oOnAndroid.git

//Update (25.09.2011)
Jak słusznie zauważył mój przyjaciel Michał, skoro otwieramy połączenie do bazy danych, to musimy je również zamknąć. Można to zrobić w MainActivity.java w przeciążając metodę onDestroy():

@Override
protected void onDestroy() {
    Db4oHelper db4oHelper = new Db4oHelper(this);
    db4oHelper.close();
    super.onDestroy();
}

poniedziałek, 2 maja 2011

Warunkowa kompilacja j2me w srodowisku NetBeans

Pisanie aplikacji na urządzenia mobilne w j2me nie jest prostą sprawą. Niby specyfikacja KVM (Kilobyte Virtual Machine) jest jedna i narzucona przez Oracle’a (dawniej Sun’a), ale konkretną implementację dostarcza producent danego telefonu komórkowego. Ponadto mamy sporo różnych modelów telefonów, różniących się od siebie wielkością ekranu, ułożeniem przycisków, szybkością procesora itd. Często przychodzi potrzeba dostarczenia aplikacji zoptymalizowanej pod konkretny telefon. Przedstawię poniżej w artykule jak można tego dokonać za pomocą warunkowej kompilacji w NetBeans’ie.

Warunkowa kompilacja to bardzo stary pomysł znany mi z czasów języka C (a może i był używany wcześniej). Polega ona na dodaniu do kodu źródłowego pewnych instrukcji, które zostaną wykonane jeszcze przed właściwą kompilacją. Spowoduje to wybranie odpowiednich fragmentów kodu, które zostaną dołączone do wynikowego programu. Projektanci języka Java całkowicie zrezygnowali z warunkowej kompilacji ze względu, że jest ona wrogiem numer 1 obiektowości. Gdy J2ME ujrzała światło dzienne i gdy coraz więcej telefonów zaczęło wspierać tą funkcjonalność, zrozumiano że jednak pewna możliwość konfigurowania kodu przed właściwą kompilacją jest niezbędna. I tak się narodziła warunkowa kompilacja w NetBeans'ie. Oczywiście wiem, że obecnie mamy XML’e, Dependency injection, Inversion of control i inne możliwości konfiguracji naszych aplikacji, ale nie mają one zastosowania w świecie j2me. Powstały co prawda projekty Signal Framework i Spring ME coś ala IoC dla j2me, ale jak dla mnie to sztuka dla sztuki i zastosowanie zerowe (i tak trzeba całość kompilować).

Dobra czas przejść do konkretów. Poniżej prezentuję fragment kodu, który używam w swojej aplikacji, z wykorzystaniem warunkowej kompilacji:

private void drawHelpMenu(Graphics g) {
//#if MobileTouchScreen
    helpSprite.setPosition(getWidth() - helpSprite.getWidth(),
            getHeight() - helpSprite.getHeight());
    helpSprite.paint(g);
//#else
    String  back = I18n.getText(I18n.LESSON_HELP);
    g.setFont(getSmallFont());
    g.drawString(back, getWidth(), getHeight(),
            Graphics.RIGHT | Graphics.BOTTOM);
//#endif
}

Interesujące fragmenty to te zaczynające się od //#. Są to instrunkcje preprocesora. Jak to działa? Gdy mamy ustawione ability MobileTouchScreen, to wówczas linijki 3-5 zostaną skompilowane, w przeciwnym wypadku linijki 7-10 zostaną wstawione w ciało metody drawHelpMenu(...). Prawda ze proste?

Teraz nadszedł czas na zarządzanie naszymi “zdolnościami” (chyba nienajlepsze tłumaczenie). Klikamy prawym przyciskiem myszy na nazwę projektu i wybieramy z menu opcję Properties. Tam w kategorii Abilities możemy zobaczyć jakie mamy ustawione właściwości dla obecnej konfiguracji naszego projektu. Właściwości mogą posiadać wartość, ale nie muszą.


Proponuję teraz utworzyć sobie nową konfigurację. Z pola Project Configuration wybieramy Add Configuration I wpisujemy nazwę nowej konfiguracji I następnie klikamy OK. Możemy tutaj jeszcze wybrać szablon, na podstawie którego zostanie utworzona konfiguracja.


Po kliknięciu OK wracamy do poprzedniego ekranu i teraz możemy modyfikować naszą konfigurację. Najpierw musimy odznaczyć pole Use Values from „DefaultConfiguration”. Dzieki temu przycisk Add staje się aktywny. Klikamy i w nowym oknie wpisujemy nasze ability MobileTouchScreen.


Klikamy OK i w oknie z właściwościami naszego projektu pojawiła się nowa pozycja w tabelce właściwościami danej konfiguracji.

Teraz chcąc skompilować projekt, używając nowej konfiguracji, należy ją wybrać z menu w górnej części okna.


Jak popatrzymy na nasz kod to zobaczymy, że NetBeans koloruje tło pod kodem nalezącym do warunkowej kompilacji:


Dodatkowo dodał komentarze na początku linii pomiędzy //#else a //#endif. Dzięki temu kod nie będzie dołączony do kompilowanej aplikacji. Zmiany te są zapisywane w pliku na dysku (polecam sprawdzić) i NetBeans nie zawsze chce się odświeżyć (w sensie widoku pliku źródłowego). Warto wtedy zamknąć i otworzyć na nowo plik, aby wiedzieć co edytować. Ponadto mechanizm ten zapewnia bezbolesny eksport do innego środowiska IDE, które nie wspiera tego mechanizmu. Całość zostanie potraktowana jako zwykły komentarz.

Z drugiej strony mechanizm może utrudniać merge’owanie i śledzenie zmian w kodzie. No chyba że wszyscy będą pamiętać, aby przed commit’em jedną, zawsze tą samą konfigurację ustawić.

Czy blok if else endif to wszystko co daje nam warunkowa kompilacja w NetBeans? Nie. Z ciekawszych opcji mamy jeszcze //#condition NAZWA_ABILITY i dzięki której decydujemy czy dany plik ma być dołączony do danego build’a, czy nie. Deklaracja musi być jednak umieszczona na początku pliku!

No dobra, mamy już skonfigurowany kod, ale co z innymi zasobami? Np, z grafiką, którą np. potrzebujemy tylko do wersji z obsługiwanym ekranem dotykowym? Mamy możliwość zdefiniowania zasobów, które mają się w takiej konfiguracji znaleźć. W tym celu przechodzimy do właściwości projektu i wybieramy Librares & Resources. Odznaczamy Use Values from „DefaultConfiguration” i już możemy dodawać katalogi, biblioteki i inne wymagane projekty.

Nie pozostaje teraz nic innego jak wziąć się do roboty i zacząć odpowiednio dostosowywać nasze mobilne aplikacje.

czwartek, 28 kwietnia 2011

Asocjacje plików w Eclipse

Mój poprzedni wpis Podświetlanie zmian kodu w Eclipsie, w którym pokazałem pewną wskazówkę ułatwiająca naszą codzienną pracę, był bardzo często czytany. Z portalu dworld.pl, który blogrolluje (nie wiem na ile to dobre słowo) ciekawe okołojavowe wpisy z całej polskiej blogosfery, miałem ponad 100 przekierowań. Byłem, więc w czołówce najpopularniejszych wpisów z ostatniego miesiąca. Podbudowany tym wydarzeniem postanowiłem pójść za ciosem i przedstawić kolejną przydatną (może nie koniecznie ciekawą) opcję ze środowiska Eclipse. Pomysł na to podrzucił mi kolega z pracy - Sebastian - któremu za pomoc z tego miejsca dziękuję. Ułatwiło to trochę moją codzienną pracę.

Często się zdarza, ze w naszej pracy mamy nie tylko do czynienia z kodem, ale także z grafiką. Nawet proste strony internetowe zawierają zawsze jakąś grafikę. Najłatwiej ją nam wyszukać i otworzyć do edycji z pomocą opcji Open Resource (Ctrl + Shift + R). Widzimy wtedy okienko jak poniżej:


Niestety chcąc dokonać edycji, nie zawsze chcemy użyć do tego domyślnej aplikacji z systemu operacyjnego. Wybranie opcji Open With i znalezienie żądanego programu, nie powoduje, że nasz wybór będzie zapamiętany. A szkoda.


Chcąc zmienić domyślny edytor, np. grafiki, należy wejść w menu Window -> Preferences -> General -> Editors -> File Associacions. Dodajemy interesujące nas rozszerzenie i aplikację, którą chcemy urzywać do edycji.


W ramach ciekawostki powiem jeszcze, że MS Paint jest umieszczony w katalogu Windows\System32, gdyby ktoś szukał. Ciekawe położenie. Wygląda na to, że narzędzie to jest bardzo ważne w systemie i na pewno jest mocno używane przez resztę Windowsowych kluczowych funkcjonalności. Kojarzę, że we wcześniejszych wersjach, było chyba trochę lepiej, tzn. gdzieś indziej leżał ten program. Degradacja architektury?

wtorek, 5 kwietnia 2011

Podświetlanie zmian kodu w Eclipsie

Jeśli chodzi o preferowane środowiska programistyczne, to nie jestem ani zagorzałym fanem Eclipse, ani NetBeans'a. Każde z nich ma swoje wady i zalety, każde sprawdza się inaczej w różnych zadaniach. Muszę w końcu na poważnie usiąść do poznawania IntelliJ IDEA i może wtedy sprawa ulubionego IDE się wyjaśni. Tymczasem chcę opisać pewną funkcjonalność, do której się przyzwyczaiłem w NetBeans'ie, a której mi trochę brakowało w Eclipsie. Pokażę również, jak można ją aktywować w tym drugim środowisku.

Funkcjonalność o której wspomniałem to zaznaczanie fragmentu kodu, który został zmodyfikowany (lub dodany). W NetBeans'ie wyglada to tak:


Po lewej stronie, między numeracją linii a kodem, widzimy dwa paski: niebieski i zielony. W Eclipsie trochę mi tego brakowało, ale ostatnio poszukując rozwiązania czegoś tam, przypadkiem trafiłem na potrzebną mi opcję. Podświetlanie zmian w kodzie można włączyć w Preferences w Quick Diff. Najlepiej śledzić zmiany w stosunku do repozytorium, w moim przypadku SVN'a.


Przyda się jeszcze tuning kolorów. Te z NetBeanas'a całkiem mi pasują. Zmiany są kolorowane na (RGB) 160 200 255 (#A0C8FF), a dodane linijki na (RGB) 150 255 150 (#96FF96). Wprowadzając te kolory do Eclipse, okazuje się, że są one trochę inne niż w NetBeans'ie (słabiej widoczne, zlewają się z szarym paskiem).


Nie wiem czemu, ale środowisko (Eclipse Galilieo) trochę inaczej wyświetla / interpretuje te kolory. Po kilku eksperymentach z wartościami RGB, doszedłem do zbliżonych kolorów. Zmiany należy ustawić na 18 119 255 (#1277FF), a dodane fragmenty na 0 255 0 (#00FF00). Efekt jest następujacy.


No już lepiej :) Co prawda, już na tym prostym przykładzie widać, że te dwa środowiska, w różny sposób interpretują wprowadzane zmiany, czasami trochę błędnie wyświetlając, co zostało zmienione, a co dodane. No ale trudno. Ważne, że teraz widać, w której części pliku się coś zmieniło i czy dane zmiany są nam dalej potrzebne. Mi to pomaga przeglądając zmiany przed commitem.

środa, 16 marca 2011

Parsowanie plików Excela

Często zachodzi w naszym świecie potrzeba parsowania plików Excela. Jak to powiedział Sławek Sobótka,  podczas prezentacji pt. „Domain Driven Design” – Wszystko ma swoje miejsce i wszystko jest na miejscu [video 1] [video 2] w ramach WrocławJUG: „[...] ludzie biznesu traktują Excela jako notatnik”. I rzeczywiście. Dla ludzi, którzy mają styczność na codzień w pracy z tabelkami, Excel jest wygodnym i niezastąpionym narzędziem. Warto więc zaznajomić się ze sposobem odczytu danych z arkuszów kalkulacyjnych. Nie będę opisywał jak odczytywać diagramy UML’owe zapisane w Excelu (jak to przedstawił Sławek), ale pokażę poniżej proste parsowanie arkuszy kalkulacyjnych.

Szukając biblioteki javovej obsługującej wspomniane akrkusze natrafiłem najpierw na Java Excel API. Gdzieś przeczytałem, że jest ona łatwiejsza w użyciu niż inne rozwiązania i zacząłem z niej korzystać. Niestety szybko się okazało, że biblioteka słabo radzi sobie z krzaczkami (obcojęzycznymi znakami) i kontynuowałem moje poszukiwania. Natrafiłem wówczas na Apache POI.

Apache POI jest biblioteką nie tylko potrafiącą współpracować z plikami Excela, ale również innymi dokumentami Microsoft Office’a. Chcąc odczytać coś z arkusza kalkulacyjnego, musimy najpierw utworzyć obiekt typu Workbook.

Workbook wb = new HSSFWorkbook(
    new POIFSFileSystem(new FileInputStream(filename)));

Mając już taki obiekt, możemy sprawdzić z ilu zakładek składa się nasz dokument (wb.getNumberOfSheets()), pobrać wszystkie obrazki dokumentu (getAllPictures()), czcionkę z danej komórki (getFontAt(...)) i sporo innych. Aby odczytać dane z konkretnej zakładki, należy ją najpierw pobrać:

Sheet sheet = wb.getSheetAt(...);

Teraz jak już mamy obiekt typu Sheet możemy iterować po danej zakładce w następujący sposób:

for (Row row : sheet) {
    for (Cell cell : row) {
        // …
    }
}

Teraz zostaje już tylko odczytać zawartość danej komórki:

String str = cell.getStringCellValue();

Poniżej prezentuję prosty kod metody wyświetlającą zawartość całego pliku:

public static void showAll(String filename) throws IOException {
    Workbook wb = new HSSFWorkbook(
        new POIFSFileSystem(new FileInputStream(filename)));
    for(int i=0; i < wb.getNumberOfSheets(); i++) {
        Sheet sheet = wb.getSheetAt(i);
        for (Row row : sheet) {
            for (Cell cell : row) {
                String str = cell.getStringCellValue();
                System.out.println(str);
            }
        }
    }
}

Do czego używam tej biblioteki? Na przykład do internacjonalizacji aplikacji. W pliku Excela przygotowuję sobie tłumaczenia używane w tworzonej aktualnie aplikacji. Następnie puszczam taki plik przez mój mały programik, która czyta odpowiednie kolumny i generuje pliki properties. Zgodnie z tym co kiedyś mówił Marek Berkan podczas prezentacji "Automatyczne generowanie kodu" na 4Developers 2010 warto jest jak najwięcej kodu generować automatycznie. Dlatego, po za samym plikiem properties, generuję sobie również plik javowy, zawierający zdefiniowane stałe, których mogę używać w kodzie, chcąc się dostać do danego tekstu. Dzięki temu jak nazwa jakiejś właściwości się zmieni, wygeneruje się inny kod i kompilator będzie krzyczał, gdy gdzieś jeszcze używam nieaktualnej stałej. Chroni mnie to przed błędami w aplikacjach związanymi z tłumaczeniami.

Oczywiście sposobów na wykorzystanie owej biblioeki jest multum, więc zachęcam do testowania.

czwartek, 24 lutego 2011

Hamburg wrażenia po miesięcznym pobycie


W ostatnim przebywam tymczasowo w Hamburgu (już miesiąc), więc już najwyższy czas aby swoje przemyślenia wyrazić, co mi się tutaj podoba, a co nie. To co na samym początku, zaraz po przyjeździe tutaj mnie zachwyciło, to możliwość legalnego, bezstresowego spożywania alkoholu w miejscach publicznych. Zaraz po zameldowaniu się w hotelu, poszedłem z kolegami na piwko, oczywiście w plener. I nawet pogoda nie przeszkadzała (przynajmniej mi), a był zimny styczeń w tym roku. Szczęściem naszym było, że znaleźliśmy otwarty sklep. Ogółem w Niemczech wszystko w Niedziele jest zamknięte. Wyjątkiem są piekarnie (zazwyczaj czynne od rana do popołudnia), muzea i inne instytucje, które muszą być otwarte. Nawet wielkie centra handlowe i budki z kebabem są pozamykane. Znaleźć sklepy czynny w Niedzielę, to naprawdę trzeba mieć szczęście. Muszę przyznać, że w Niemczech jest duża różnorodność jeśli chodzi o gatunki piwa. Jest w czym wybierać i smakują dobrze. Zazwyczaj dla każdej marki piwa są 3 gatunki: pszeniczne, porter i pils. A często jest ich więcej. Inną typową sprawą w Niemczech są drzwi do mieszkań w bloku. Nie montuje się tutaj klamek od strony zewnętrznej i aby otworzyć drzwi potrzebne są klucze. Biada temu, kto zapomni klucza wychodząc z mieszkania. Mi się raz prawie to zdarzyło (chciałem tylko światło na korytarzu zapalić), ale na szczęście zdążyłem „złapać” zamykające się drzwi. Inaczej było by po imprezie ;) Inną ciekawostką, jest pralka, która zazwyczaj znajduje się w piwnicy. Ja akurat mam małą kawalerkę i jeszcze to jakoś rozumiem, ale podobno tutaj to typowe. Dodatkowo, aby skorzystać z takiej pralki, trzeba wrzucić pieniążki do skrzynki doprowadzającej prąd. W moim przypadku jest to 1,5 Euro. Dodatkowo zazwyczaj w takiej pralni znajduje się jeszcze mechaniczna suszarka (również na pieniążki). Co ważne, to to aby wrócić do pralni przed końcem czasu wyświetlanego na urządzeniu połykającym monety. Ja za pierwszym razem tego nie wiedziałem i musiałem dodatkowe monety wrzucić, aby przywrócić zasilenie na chwilę i otworzyć drzwi od pralki. Rozumiem, że Niemcy są skąpi, że cię nie opłaca itd, ale takie rozwiązanie mi się niezbyt podoba. Kolejna sprawa to komunikacja miejska. W Hamburgu jest ona bardzo rozwinięta. Mamy tutaj U-Bahn, S-Bahn, A-Bahn (cokolwiek to jest), kolej regionalną, Metrobus(typowe autobusy), Schnellbus (szybkie połączenie z dzielnicami robotniczymi), Ellbus (dla terenów gdzie nie ma U-Bahn’a, czy S-Bahna), nocne autobusy no i ... statki miejskie. W końcu to miasto portowe (drugi w Europie pod względem wielkości port obsługujący kontenerowce). Niestety za taką sieć komunkacyjną trzeba sporo płacić. Miasto jest podzielone na sporo stref, które decydują o cenie przejazdu. Przykładowo bilet miesięczny na 2 strefy to 58 Euro. Dodatkowo trzeba mieć zdjęcie, aby taki bilet kupić. Warto o tym pamiętać przed przyjazdem tutaj. Ponadto w autobusach panuje dziwny zwyczaj / obowiązek. Codziennie po 21 i w przez całą Niedzielę, wchodzi się przednimi drzwiami i pokazuje bilet kierowcy. Czasami niektórzy wchodzą środkowymi drzwiami, ale jak będzie upierdliwy kierowca, to będzie przez mikrofon prosił aby podejść do przodu i pokazać przejazdówkę. W przeciwnym przypadku będzie stał na przystanku, aż do skutku. No i kierowcy są tutaj bardziej uprzejmi i zawsze czekają na pasażerów biegnących z daleka na autobus i otwierają im drzwi. Bilet jednonarazowy można również kupić u kierowcy. Spodobał mi się ich sprzęt. Mają niewielki terminal, który drukuje bilet i fajny automat do wydawania reszty. Są na nim przyciski, które po naciśnięciu wypluwają daną monetę do „kubeczka”, z którego bardzo łatwo i wygodnie można zabrać drobne. Również informacja, o tym gdzie autobus jedzie i gdzie się zatrzymuje jest łatwo dostępna w autobusie. Przy ważniejszych przystankach, po za słownym komunikatem po Niemiecku, jest on również po Angielsku. No i oczywiście są wyświetlacze diodowe, wypisujące nazwę następnego przystanku. Nie lecą tam przesuwające się reklamy tekstowe jak np. we Wrocławiu. Również na większości przystanków są zamontowane tablice, informujące za ile minut będzie autobus / metro. Bardzo dobre rozwiązanie i co najważniejsze działa. Nie jest to zwykły plan rozkładu jazdy, a dokładna informacja co za jaki czas przyjedzie. Nie zdażyło mi się zauważyć, aby to błędnie funkcjonowało. Kiedy doczekamy się czegoś takiego w Polsce? Nie mam pojęcia. Standard komunikacyjny jest więc tutaj wysoki. Dodatkowo niedawno instytucja zajmująca się transportem miejskim, wprowadziła ciekawą „usługę”. Jeżeli transport spóźni się więcej niż 20 minut, to oddają połowę ceny biletu. Świadczy to o wysokim standardzie tych usług. Podobna promocja w Polsce mogła by zrujnować komunikację miejską w większych miastach. Dla tych którzy nie lubią komunikacji miejskiej, jest w Hamburgu ciekawa alternatywa. Otóż w wielu punktach miasta, są stojaki z rowerami. Po wcześniejszym zarejestrowaniu się, można taki rower wypożyczyć, przejechać potrzebny kawałek i oddać go na innym „przystanku”. Podobne rozwiązanie chce wprowadzić Wrocław. Tutaj to się sprawdza i ludzie korzystają z tego. No i pierwsze pół godziny gratis :) Jest tu sporo ścieżek rowerowych, albo wydzielonych pasów na ulicy, więc jest gdzie jeździć. Co zauważyłem, to sporo osób tutaj biega dla sportu, zwłaszcza w okolicach Alster. Aż głupio mi było tamtędy ostatnio iść. Czułem się jak jakbym biegał na autostradzie pomiędzy samochodami. Największe wrażenie zrobił na mnie mężczyzna, biegający razem z wózkiem dziecięcym (taka wyższa forma spaceru). W Hamburgu jest sporo mostów. Kiedyś myślałem, ze we Wrocławiu jest dużo mostów (220 wg Wikipedii). A tu jest 2500 mostów (również wg. Wikipedii)! Tak, to więcej niż w Wenecji, Amsterdamie i Londynie razem wziętych. Naprawdę, zazwyczaj z każdego mostu widać kilka następnych i czasem są kilka metrów od siebie. Co mnie jeszcze tutaj zaskoczyło, to spora liczba b-boy’i tańczących na ulicach, zbierając przy tym drobne. Poniżej linki do YouTube’a: B-boys aus Hamburg prt. 1 B-boys aus Hamburg prt. 2 Hamburg dance show Po za b-boy’ami spotkałem na ulicy jeszcze raperów, sprzedawających swoją muzykę. Po prostu szedłem sobie ulicą i ktoś się mnie pytał czy słucham hip-hopu. Odpowiadałem że tak i w tym momencie dawali mi swoje słuchawki i puszczali swój kawałek do posłuchania. Ich płyty można również kupić w normalnych sklepach, ale widocznie nie mają dużego popytu, skoro dodatkowo rozprowadzają je tą metodą (trochę jak nielegale). Co ważne są one po niższej cenie niż w sklepie. Jedna taką płytę kupiłem i dzięki temu mam rzadką okazję posłuchania rapu z Gujany. Odnośnie zakupów, to warto sprawdzić jaką ma się kartę płatniczą, przed przyjazdem tutaj. Otóż karty Visa, nie są akceptowane we wszystkich sklepach. Pytałem jednego Niemca dlaczego, to twierdził, ze to ze względów bezpieczeństwa. Na karcie Visa (i paru innych) widnieje numer, za pomocą którego można dokonywać zakupów, jak kartą kredytową. No i jak się płaci w sklepie to ktoś może zapamiętać ten numer i użyć w niepowołanym celu. W sumie to dobre myślenie. Mi ogółem cały ten pomysł robienia zakupów jedynie za pomocą numeru karty kredytowej bez dodatkowej autoryzacji się nie podoba, ale to już osobny temat. Upewnijcie się więc najpierw, czy w danym sklepie możecie płacić swoją kartą. Na koniec jeszcze mała ciekawostka. Jest piosenka o tym, jak w Hamburgu mówi się na „do widzenia”: In Hamburg sagt man Tschüss. O ile „Tschüss”, mówione na pożegnanie, jest ogólnie znane i używane w całych Niemczech, tak na przywitanie mówi się tutaj „Moin”. Jest to tutaj bardzo popularna forma przywitania, ładnie to brzmi, a w szkołach tego nie uczą. A szkoda.

sobota, 19 lutego 2011

Kilka porad na temat MIDP Visual Design w Netbeans'ie

Dzisiaj chciałbym opowiedzieć o kilku sztuczkach, w MIDP Visual Design, który jest dostępny w Netbeans’ie. Tak wiem, że technologia J2ME (czy też JME) jest już trochę przestarzała, gdyż teraz mamy Androidy iPhone’y, BlackBery, Windows 7 i inne ciekawsze cuda na kiju ;) Zamierzam jednak jeszcze kilka postów o j2me na blogu opublikować, ot tak dla potomności.

Z opcji MIDP Visual Design możemy skorzystać tworząc nowy projekt z grupy „Java ME” typu „Mobile Application” w NetBeans’ie. Wystarczy nie odznaczać (gdyż domyślnie jest zaznaczony) CheckBox’a „Create Hello MIDlet”.


Można również do istniejącego projektu dodać Visual MIDlet i uzyskamy podobny efekt.

Narzędzie pozwala nam w prosty sposób zbudować menu użytkownika, przechodzenie pomiędzy ekranami itp. Mamy ładny podgląd gdzie z danego miejsca możemy się przemieścić, czyli widzimy przepływ aplikacji (menu). Należy pamiętać, że generowane menu oparte jest na komponentach wysokopoziomowych (tych dziedziczących z klasy Screen). Przykładowy screen jak może taki przepływ wyglądać poniżej.


Oczywiście w ten sposób nie zrobimy całej aplikacji. Mamy możliwość dodawania kodu w pewnych miejscach i większość rzeczy można wyklikać. Generalnie narzędzie świetnie się nadaje do prototypowania, gdy na szybko trzeba coś pokazać. Nie widzę jednak przeciw wskazań, do użycia tego również na produkcji. Generowany kod jest całkiem dobry. Poniżej kilka wskazówek, związanych z tym oto narzędziem:

1. Możemy wybrać w jaki sposób poszczególne komponenty są inicjowane. Po wybraniu danego Screena w oknie Properties widzimy dostępne opcje. Po za zmianą wyświetlanego tekstu i innych właściwości, możemy wybrać czy mają być Lazy Initialized czy nie.


Proponuję każdemu sprawdzić, jaki kod zostaje wygenerowany przy zmianie tego komponentu. W małych aplikacjach może to nie mieć wielkiego znaczenia, czy komponent jest lazy czy nie, ale te duże / ciężkie komponenty (lub rzadko używane) powinny być leniwie inicjowane. Oczywiście część komponentów może być inicjowana tak, a druga inaczej.

2. Możemy również zmienić sposób generowania logiki, odpowiedzialnej za przechodzenie pomiędzy kolejnymi ekranami. Domyślnie to, która opcja z menu została wybrana, sprawdzane jest na podstawie etykiety (label’ki) przypisanej do danego elementu ekranu. Przykład poniżej:

public void mainMenuAction() {
    // enter pre-action user code here
    String __selectedString = getMainMenu().getString(getMainMenu().getSelectedIndex());
    if (__selectedString != null) {
        if (__selectedString.equals(“Etykieta”)) {
            // ...

Włączając opcję “Index Based Switch” powyższy kod zostanie przekształcony w coś takiego:

public void mainMenuAction() {
    // enter pre-action user code here
    switch (getMainMenu().getSelectedIndex()) {
        case 0:
            // ...

Zachowanie to może mieć znaczenie wówczas, gdy chcemy wprowadzić internacjonalizację do naszej aplikacji i podmianę tekstów na elementach „w locie”. W drugim przypadku logika aplikacji w żaden sposób nie zależy od przypisanej etykiety w danym komponencie, a jedynie na jego położeniu. Po takim zabiegu podmiana tekstów jest prostsza.

3. Odnośnie internacjonalizacji, to w większości kontrolek mamy możliwość podmiany wyświetlanego na niej tekstu (dziedziczymy z klasy Displayable metodę setTitle()). Problem jest jednak z obiektami typu Command, które są immutable, gdyż nie posiadają metod modyfikujących ich stan. Można za to skorzystać z następującej sztuczki: usunąć z danego ekranu istniejące obiekty Command, utworzyć je na nowo i podpiąć. Przykład poniżej:

getSettingsMenuList().removeCommand(getBackCommand());
backCommand = null;
getSettingsMenuList().addCommand(getBackCommand ());

W pierwszej linii usuwamy obecną powiązaną komendę z danym ekranem. W drugiej linii zerujemy referencję do obiektu zwracanego przed getBackCommand(). Na koniec tworzymy obiekt na nowo (wywolanie getBackCommand()) i przypisujemy nową komendę do żądanego elementu. Korzystamy tutaj z faktu, że dana komenda jest leniwie inicjowana i po wejściu w metodę  getBackCommand(), zostanie ona na nowo utworzona.

4. Generalnie często początkujący programiści zderzający się z MIDP Visual Design wkurzają się, że nie mogą tu wszystkiego zrobić czego chcą. Według mnie wszystko da się wyklikać (w zakresie oferowanym przez edytor), ewentualnie dopisując niewielkie kawałki kodu w miejscach, w których edytor nam na to pozwala. Na prawdę nie znalazłem niczego, w czym by edytor mnie ograniczał.

Jednakże chcąc się pozbyć wsparcia ze strony MIDP Visual Design można wykonać pewien trick. Usuwając z dysku plik .vmd i wszystkie komentarze, generowane przez edytor, z pliku .java. Oczywiście musimy zrobić to w innym edytorze tekstowym, a nie pod NetBeans’em. Nie będziemy mogli również wrócić do poprzedniego stanu, ani więcej zobaczyć przepływu aplikacji dla naszego kodu.

Usunięcie komentarzy (przynajmniej część) z pliku z kodem, jest równie ważne jak usunięcie pliku *.vmd. W przypadku usunięcia tylko tego pliku możemy napotkać na problemy z otwarciem projektu pod NetBeans’em.

Poniżej początki komentarzy dodawanych przez NetBeans’a:

//<editor-fold
//</editor-fold
//GEN-LINE
//GEN-BEGIN
//GEN-END

To tyle na dzisiaj. Zachęcam do korzystania z tego edytora. Jak było coś niejasne to piszcie!

niedziela, 9 stycznia 2011

Co najbardziej boli przy poznawaniu nowych technologii?

Chciałbym się w poniższym wpisie podzielić swoimi przemyśleniami na temat tego, co sprawia, że siadając do poznawania nowej technologii, bardzo często tracimy dużo czasu nad jakąś „pierdołą”. Ostatnio musiałem / chciałem napisać sobie coś w JavaScript. Miał to być pewien gadżet na bloga, gdyż brakowało mi pewnej funkcjonalności na blogerze. Nigdy wcześniej nie korzystałem z JavaScript i nie znałem podstaw, ani dokładniejszych założeń języka. Jako że nie było to zajęcie na dłużej, postanowiłem szybko znaleźć jakieś rozwiązanie, zaimplementować, potestować, zastosować i zapomnieć. Nie chciałem więc się mocno w ten język zagłębiać.

Poszedłem, więc do Empika w poszukiwaniu natchnienia. Znalazłem pierwszą lepszą książkę do JS i zacząłem przeglądać. No dobra mamy zmienne, pętle, operacje matematyczne, możemy zmieniać widoczność elementów na stronie, modyfikować ich style, itd. Po szybkim rozeznaniu i konsultacji z ziomkiem bawiącym się kiedyś tym językiem, przystąpiłem do pracy.

Po niedługim czasie pierwsza wersja skryptu zaczęła już działać. Przy testowaniu jednak zauważyłem, że dla pewnych danych wejściowych coś nie działa. Przyczyną tego stanu było dynamiczne typowanie które powodowało, że operacje matematyczne wykonywały się na liczbach zmiennoprzecinkowych (a nie na wartościach całkowitoliczbowych jak oczekiwałem). Po usunięciu tego problemu dalej jednak coś nie grało.

Okazało się że JavaScript domyślnie przy konwersji float -> int zaokrągla liczby do najbliższej, a nie bierze części całkowitej. Konieczne okazało się zastosowanie funkcji Math.floor(), aby było po mojemu.

Problem miałem jeszcze, po dodaniu skryptu do bloga, bo w FireFox'ie nie chciało działać. Znalazłem wtedy w tej przeglądarce ciekawą opcję „Konsola błędów” w menu „Narzędzia”. Dzięki temu szybko dowiedziałem się o co chodzi i po szybkiej podpowiedzi od ziomka poprawiłem skrypt.

Moje pytanie brzmi co sprawiło, że napotkałem na takie problemy? Otóż brak wiedzy na temat podstaw języka JavaScript. Nie wiedziałem, że domyślnie operacje liczbowe dokonywane są na typach zmiennoprzecinkowych, że zaokrąglanie liczb jest do najbliższej i jeszcze parę innych drobiazgów. Są to niby drobnostki, ale powodują one, że nasz kod robi coś innego niż się spodziewamy. Sporo czasu poświęciłem, aby dojść do tego, dlaczego mój kod działa tak a nie inaczej. Takie drobnostki / szczegóły / detale przy używaniu języka, którego się nie zna, prowadzą do dużej straty czasu na szukanie błędu i rozwiązania.

Z podobną sytuacją spotkałem się już wielokrotnie. Np. tablice w Matlabie są numerowane od jedynki, co dla wieloletnich programistów C\C++, Javy początkowo irytuje. Przypomina mi się również sytuacja znajomego, który jest fanem C#, a musiał coś w Javie zrobić. Pytał mnie się: „Dlaczego kolekcje nie działają mu tak, ja sie tego z dokumentacji spodziewa? Przeciążył przecież metodę equals()”. Od razu zapytałem, czy przeciążył też metodę hashCode(), gdyż znałem kontrakt jaki obowiązuje te dwie metody i wiedziałem jak działają kolekcje. Sytuacja od razu stała sie jasna.

Jaka z tych przemyśleń nauka na przyszłość? Niewielkie niuanse pomiędzy poszczególnymi językami programowania bardzo dają się we znaki. Warto dlatego, zanim co kol wiek w danym języku napiszemy, poczytać trochę o podstawach i założeniach danego języka. Z drugiej strony długo szukając rozwiązania jakiejś drobnostki, albo się zniechęcimy do danego języka, albo zapamiętamy o co chodziło na bardzo długo.