Piwo to moje paliwo

February 7th, 2010

I jebać zakaz reklamy alkoholu

i7500 plugin do wordpress’a

February 4th, 2010

Zdecydowanie wygodniejszy do pisania postów z komórki niż przegladarka. Zapisuje sie na betatestera.

JasperReports, iText, Groovy – poranne zamotanie

February 3rd, 2010

W projekcie zaczynamy używać biblioteki iText i JasperReports. Wszystko ładnie pięknie, ale:

  • iText mamy w wersji 5.0.0.
  • JasperReports w wersji 3.5.3.
  • Używamy mavena.
  • JasperReports używa iText

Pierwszy problem to dość poważna wpada ekipy od iTexta. Otóż wersji 5 nie ma w repo mavena. Dopinamy więc ja ręcznie. Następnie okazuje się, że JR wykorzystuje iText, ale w wersji 2. niby wszystko bangla, ale różnica pomiędzy iText 5 i 2 jest niewielka jednak bardzo bolesna. Polega na zmianie nazw pakietów. Zamiast com.lowagie.text w wersji 5 mamy com.itextpdf.text. Zatem musimy mieć dwie różne biblioteki w projekcie. Jeżeli w mavenie podepniemy z rozpędu iText 5 do grupy com.lowagie to oczywiście wersja 2 zostanie zignorowana przy sprawdzaniu zależności JR. Spowoduje to brak klas z pakietu com.lowagie.text i tym samym radosna wyjebkę całości. Poniżej poprawny kawałek pom.xml:

Listing 1. Poprawnie złożony pom.xml


	itext
	itext
	5.0.0
	system
	${basedir}/libs/iText.jar


	com.lowagie
	itext
	2.1.7


	jasperreports
	jasperreports
	3.5.3

tak będzie git.

Kolejna ciekawostka to błąd java.lang.NoClassDefFoundError: org/codehaus/groovy/control/CompilationFailedException w trakcie generowania raportu. Okazuje się, że jeżeli używa się iReport do tworzenia szablonów to do tagu jasperReport jest dodawany atrybut language=”groovy”. Na rozwiązanie problemu są dwie drogi. Pierwsza dopiąć Groovy, druga wyjebać atrybut. Pierwsza metoda wymaga jednak użycia paczki groovy-all. Dodajemy zatem:

Listing 2. groovy-all w pom.xml


	org.codehaus.groovy
	groovy-all
	1.7.0

Zaletą tego rozwiązania jest możliwość, dania użytkownikom iReport i powiedzenie, by sami ładowali raporty na serwer.

koniec

uff…

Co znaczy Honor?

February 2nd, 2010

No właśnie co oznacza honorW? Wiele osób, szczególnie polityków, mówi o honorze o hańbie i o tym jacy to oni nie są honorowi. Jest jednak jeden człowiek, który choć nie uczestniczy już w życiu publicznym może o sobie powiedzieć, że jest honorowy. Generał Wojciech Jaruzelski w swojej opinii na temat filmu “Generał” mówi:

twórcy filmu przeinaczyli fakty. Zasugerował też, że działali na polityczne zamówienie. Dodał, że autorzy filmu nie są w stanie go obrazić, znieważyli natomiast wielu ludzi, którzy przeszli tę samą drogę, co on. Jaruzelski powtórzył, że nie chce się wybielać i wyraża żal za wszystkie krzywdy ludzkie, do których doszło w okresie, gdy pełnił wysokie funkcje wojskowe i państwowe.

Wiecie dlaczego jest człowiekiem honoru? Ponieważ nie zasłania się immunitetem, nie tłumaczy “dwoma jabłkami”, ale otwarcie mówi o swoich działaniach, nie wypiera się ich i bierze za nie odpowiedzialność. Niezależnie od tego czy oceniamy go źle, czy bardzo źle (bo dobrze to on nie działał) należy uznać, że jako jeden z nielicznych polityków potrafi odpowiadać za swoje czyny.

Współczesny człowiek honoru potrafi wziąć odpowiedzialność za swoje działania.

Koniec Suna

February 2nd, 2010

Strona sun.com oficjalnie zniknęła z sieci. Adres przekierowuje na oracle.com. To koniec pewnej epoki…

coby nie było java.sun.com działa dalej.

Viking Metal, lirycznie

February 2nd, 2010

Tak minie coś na Bathory naszło… a i wykonanie zacne.

Play Framework – kontroler od podstaw

February 1st, 2010

Projekt “prosty bash.org w jeden dzień” ciągnie się już drugi dzień :D W dwóch wpisach przybliżyłem już jak się ma sprawa z modelem danych w PF. Dziś opiszę jak od podstaw stworzyć kontroler i widok do jego obsługi. Generalnie zasady są proste. Rozszerzamy klasę Controller i dodajemy mapowania w pliku routes. W praktyce jest tylko trochę trudniej ;)

Założenia

Nasz kontroler będzie pozwalał na dodanie cytatu do bazy. Cytat, będzie niewidoczny na stronie głównej dopóki administrator go nie zaakceptuje. Proste :)

AddQuoteController i co z tego wynika

Nasz kontroler będzie posiadał akcję addQuoteAction oraz metodę addQuote, która będzie renderować ekran z formularzem. Na początek wyrenderujemy sobie ekran z formularzem.

Listing 1. AddQuoteController.addQuote()

package controllers;

import play.mvc.Controller;

public class AddQuoteController extends Controller {

	public static void addQuote() {
		render();
	}
}

W sumie tak wygląda najprostszy kontroler w Play Framework. Metoda render przyjmuje zmienną liczbę parametrów, które są bindowane do zmiennych w szablonie. To jednak za chwilę. Najpierw dodamy jeszcze jedną metodę.

Listing 2.

package controllers;

import java.util.GregorianCalendar;

import net.sf.oval.constraint.MinLength;

import models.Quote;
import play.data.validation.Min;
import play.data.validation.Required;
import play.mvc.Controller;

public class AddQuoteController extends Controller {

	public static void addQuote() {
		render();
	}

	public static void addQuoteAction(
			@Required(message = "Wymagane!") @MinLength(value = 10, message = "Conajmniej 10 znaków!") String content) {
		if (validation.hasErrors()) {
			render("AddQuoteController/addQuote.html");
		}
		Quote newQuote = new Quote();
		newQuote.content = content;
		newQuote.accepted = false;
		newQuote.addTime = new GregorianCalendar();
		newQuote.avgNote = 0;
		newQuote.numberOfNotes = 0;
		newQuote.save();
		Application.index();
	}
}

Dodaliśmy metodę addQuoteAction. Jako parametr przyjmuje ona klucz content. Klucza tego będziemy używać za chwilę w szablonie. Przy okazji zastosowałem dwie adnotacje. Pierwsza @Required oznacza, że parametr jest wymagany. Druga @MinLenght to minimalna wielkość parametru, przy czym w przypadku obiektów String oznacza to długość napisu. W ten magiczny sposób odrobiliśmy walidację. Jeżeli w walidatorze są błędy to przekierowujemy całość na stronę dodawania cytatu. I tu kolejna rzecz z dupy trochę.
W Springu była sobie klasa ModelAndView, która pozwalała na wykonywanie różniastych ekscesów z przekazywaniem sterowania. W skrajnym przypadku pozwalała ona na przekierowanie obsługi do innego kontrolera, pobranie wyników przechowywanych właśnie w ModelAndView zwróconym przez ten kontroler i przekazanie ich dalej do renderera. Tu niestety musimy wywoływać metodę render z parametrem w postaci String. Dla mało kumatych podpowiem, że nie można tego sprawdzić w trakcie kompilacji więc tracimy wszystkie zyski kontroli typów. No, ale jak się nie ma co się lubi to się lubi co się ma… jak mawiał pewien stary syfilityk.
Jeżeli nie ma błędów to tworzymy nowy cytat, dodajemy go do bazy i renderujemy stronę główną. Banalnie proste. Tak proste, że każdy 13-nastoletni specjalista od php z adhd będzie wstanie coś podobnego zrobić (i stać się specjalistą od PF).
Na obecnym etapie mamy gotowy kontroler, który należało by jeszcze przetestować, ale na razie sobie to odpuszczę. Testowanie w PF jest mocno dziwne, a zatem na kolejny raz się temu przyjrzymy. Przy okazji będę narzekał na gówniany pomysł na wywoływanie akcji kontrolerów (chętni mogą już w teraz w komentarzach wpisywać swoje pomysły, dlaczego ten model jest gówniany).
O czym to ja… a właśnie mamy kontroler, ale nie mamy jeszcze odpowiadającego mu widoku. Stwórzmy zatem prosty widok, który będzie zawierał pole do wpisywania komentarza i przycisk wyślij.

Widok AddQuoteController/addQuote

Play Framework generuje widoki w oparciu o język szablonów, który znowuż korzysta z GroovyW. Nie jest on trudny. Pozwala na tworzenie całkiem zgrabnych stron, a i można własne makra tworzyć.
Tworzymy zatem nowy plik w katalogu app/views/AddQuoteController i nazywamy go addQuote.html. Jego zawartość jest prosta, a to dzięki mechanizmowi rozszerzania szablonów oferowanym przez PF.

Listing 3. kompletny addQuote.html

#{extends 'main.html' /} #{set title:'Cytaty - dodaj własny' /}
#{form @AddQuoteController.addQuoteAction()}
<div>
<textarea name="content" id="content" cols="40" rows="5"></textarea>
#{ifErrors}
  #{list items:errors, as:'error'}
    #{if "content".equals(error.getKey())}
      <p class="error">
        ${error}
      </p>
    #{/if}
  #{/list}
#{/ifErrors}
</div>
<input type="submit" value="Dodaj!" />
#{/form}

Elegancko. W pierwszej linii importujemy się do szablonu strony main.html (o szablonach kiedy indziej) i nadajemy tytuł naszej stronie. Następnie tworzymy formularz, który jako akcję wykona AddQuoteController.addQuoteAction(). Nie podoba mi się obsługa błędów. Z drugiej strony kilkukrotne przelecenie przez krótką listę można wybaczyć. No chyba, że coś w API przeoczyłem (na pewno można zrobić to ładniej).
Wszystko ładnie pięknie, ale jeszcze to nie koniec naszej pracy. Najpierw musimy dodać link do strony głównej (i ją napisać), ale pominę to, ponieważ sposób walki ze stroną główną chciałbym omówić przy okazji szablonów. No właśnie link…

Routing w PF

Jest sobie plik conf/routes, który zawiera informacje na temat tego jak wygląda mapowanie pomiędzy adresami URL, a kontrolerami. Normalnie wykonalibyśmy taką operację w pliku web.xml, ale PF upraszcza życie. Idea jest prosta. Programista definiuje sposób zasady routingu, a PF odpowiednio robi dobrze. Dodanie naszego mapowania jest bardzo proste. Zresztą była już o tym mowa przy okazji modułu CRUD. Nasza reguła wygląda tak:

Listing 4. Reguła dla AddQuoteController

GET		/addQuote			AddQuoteController.addQuote

Podsumowanie

Play Framework udostępnia programistom stosunkowo dobry i wydajny sposób tworzenia aplikacji. Dzięki zastosowaniu zasady COC i sztywnemu się jej trzymaniu (co niepomiernie potrafi wkurwić) można w miarę szybko prototypować aplikację. Dodatkowym plusem jest bardzo prosty, ale elastyczny język szablonów widoku. Dzięki czemu przyuczenie do zawodu nawet debilnego programisty php z adhd nie zajmuje za dużo czasu.
Obecnie chcę rozczaić jak PF współpracuje z GWT.

Weekend z i7500

February 1st, 2010

W piątek po południu przybył do mnie mój nowy telefon. Samsung i7500 Galaxy. Na pokładzie Android, aparat 5mpx, ekran dotykowy. Brak normalnej klawiatury.

Pudło

W pudełku znajdziemy telefon, zasilacz, kabelek USB, słuchawki douszne, płytkę z softem Samsunga dla MS i instrukcję. Całość schludnie popakowana w woreczki i styropian.

Pierwsze wrażenia

Telefon jest “cegłowaty” w porównaniu z moim stary C65. Aparat jest lżejszy i cieńszy, ale szerszy i dłuższy przez co trochę inaczej układa się w ręku. Otwarcie obudowy nie stanowi problemu. Podobnie jak montaż karty SIM i akumulatora. Niestety by zamontować kartę microSD też trzeba zdjąć obudowę. Z drugiej strony kartę tą można wymienić bez wyłączania urządzenia, ponieważ slot nie jest blokowany przez akumulator.
Całość jest w estetycznej błyszczącej czerni.

Uruchomienie i obsługa

Przy pierwszym uruchomieniu system wydaje jakieś dziwne dźwięki. Na cale szczęście zestaw dzwonków jest dość duży i można sobie na spokojnie wybrać odpowiedni zestaw. Dostęp do menu z różnymi aplikacjami, ustawieniami i kontaktami jest bardzo intuicyjny. Jeżeli jednak nie miałeś do czynienia z ekranem dotykowym to może okazać się, że na początku będą małe problemy. Trzeba się przyzwyczaić.
Konfiguracja i dostosowanie do własnych potrzeb jest bardzo prosta. Menu jest w języku polskim więc nawet osoby o ubogim słownictwie nie powinny mieć problemu. Niestety nie ma menu w wersji klingońskiej.
Początkowo miałem problem z pisaniem na klawiaturze dotykowej. Nawet po obróceniu ekranu przyciski okazały się dużo za małe. Praktyka czyni jednak mistrza. Podobnie rzecz ma się z przeglądaniem stron internetowych. Trzeba dużo cierpliwości, ale mam tez okazję zobaczyć jak na tego typu urządzeniu wygląda na przykład koziolekweb. Wygląda średnio.
Bardzo łatwo jest skonfigurować obsługę sieci WiFi. Tak samo jak dość łatwo jest uruchomić moduł GPS. Niestety, żeby działał poprawnie musi mieć dostęp do sieci. Przeglądarka internetowa jest dobra. Ma całkiem duże możliwości.
Ostatnim elementem jest dostęp do Android Market. Całkiem wygodny i intuicyjny. Cóż więcej? Mieć trzeba tylko dobre łącze.

Podsumowanie

Telefon przypadł im do gustu i mam nadzieję, ze posłuży mi przez najbliższe kilka lat. Polecam go osobą, które potrzebują telefonu + dodatki, a nie dodatki + telefon.

Play Framework – moduł CRUD

January 31st, 2010

Jestem w trakcie tworzenia aplikacji “prosty bash.org w jeden dzień” i naciąłem się na ciekawego buga w PF 1.0 b833. Żeby zrozumieć skąd on się wziął należy trochę przybliżyć czym jest moduł CRUD w Play Framework.

CRUD Framework

Pod tą nazwą kryje się grupa frameworków, które udostępniają programistom zestaw narzędzi pozwalających na automatyczne tworzenie klas CrudDAO. Idea zakłada, że programista na przykład tworzy klasę modelu, która rozszerza klasę abstrakcyjną. Klasa abstrakcyjna dostarcza metod CRUD. Innym podejściem jest dynamiczne tworzenie metod i zapytań tak jak jest to realizowane w Grails. W każdym bądź razie w Play mamy do czynienia z pierwszą metodą. Opis tworzenia klas modelu znajdziecie tu.

CRUD w Play Framework

Jeżeli chcemy uruchomić moduł CRUD w Play Framework to w pliku application.conf należy od-komentować linijkę

Listing 1. uruchomienie modułu CRUD

module.crud=${play.path}/modules/crud

Następnie w pliku routes należy włączyć mapowanie do modułu CRUD:

Listing 2. konfiguracja mapowań

*      /admin              module:crud

No i gotowe. Należy jeszcze raz podpiąć projekt do naszego IDE. Od tego momentu pod adresem /admin/ mamy do dyspozycji całkiem zgrabny panel do zarządzania naszymi obiektami.

Jest jeden bug

Niestety w buildzie 833 jest bug. Otóż nie można posortować listy obiektów. Każda próba sortowania powoduje, że zawsze dostaniemy obiekty posortowane malejąco po id. Trochę do dupy… Na całe szczęście jest obejście. Moduł CRUD jak łatwo zauważyć dodał nam klasę CRUD i cały pakiet crud. Wystarczy zatem tak jak opisałem w zgłoszeniu zmienić trzy linijki.

I tyle. Generalnie CRUD z PF jest bardzo wdzięcznym podejściem do problemu i pozwala na szybkie i stosunkowo łatwe tworzenie modelu bez potrzeby kombinowania z kodem. Dostajemy na talerzu elegancki interfejs zarówno od strony programisty jak i użytkownika.

Robienie sobie szybkiego Ubuntu

January 30th, 2010

Jest kilka bardzo prostych metod, które pozwalają na bardzo dobre polepszenie jakości naszego życia i pracy z systemem Ubuntu. Niektóre z nich działają na wszystkich linuxach i warto je stosować jako obowiązkowe kroki po instalacji systemu.

Koniec dynamicznego linkowania

Każdy współczesny system operacyjny wymusza na kompilatorze tworzenie kodu wynikowego, w którym elementy związane z bibliotekami zewnętrznymi są tylko zaślepkami. Przy uruchomieniu programu następuje proces dynamicznego łączenia (linkowania) w którym zaślepki są zastępowane właściwymi odwołaniami do kodu w bibliotekach . Proces ten powoduje, że uruchomienie programu jest wydłużane o ten czas. Przykładowo OO 3.1 wstawał na moim kompie “świeżo uruchomionym” około 15 sekund przy pierwszym uruchomieniu i około 5-7 sekund za każdym kolejnym uruchomieniem w danej sesji. Dużo… jednakże wystarczy zainstalować pewien programik, który bardzo ułatwi nam życie.

Listing 1. instalacja prelink

root$> apt-get install prelink
#... komunikaty instalacji
root$> prelink -amR

Co się stało? Prelink to taka sprytna biblioteka, która na podstawie informacji z kodu źródłowego potrafi zamienić dynamiczne łączenie na statyczne referencje. Niby nic nadzwyczajnego. Robi to samo co linker tyle tylko, i tu jest pies pogrzebany, że dokonuje tej operacji na kodzie wykonywalnym. Innymi słowy modyfikuje kod programu tak by w trakcie uruchomienia nie było potrzeby dynamicznego łączenia. Wada… po każdym updacie bibliotek trzeba jeszcze raz go zapuścić. No, ale cóż… raz się żyje.
Program posiada oczywiście opcję undo

Listing 2. Prelink undo

root$> prelink -au

Którą MUSISZ uruchomić jeżeli chcesz bezpiecznie usunąć prelink. Wierz mi, nie będziesz chciał. OO 3.1 poprawił swoje czasy do 5 sekund przy pierwszym i około 3 przy każdym kolejnym uruchomieniu w danej sesji.

Co ja będę robił…

Drugim programem jest preload, który wykorzystuje metody stochastyczne do przewidywania jakie dane będą potrzebne w następnej kolejności i je zawczasu ładuje. Problemem jest, niestety, szybkie wyczerpywanie się RAM, co powoduje, że nie można odpalić JVM. Cóż… lepszą metodą jest przejście na 64-bity i włożenie z 12GB RAMu… powinno styknąć.
Na koniec instalacja i uruchomienie:

Listing 3. instalacja preload

root$> apt-get install preload
#... komunikaty instalacji
root$> /etc/init.d/preload start

Ręczne uruchomienie nie powinno się wydarzyć, ale nie zawsze automatyczne zaskoczy.

Zmiana obsługi wielu rdzeni przy starcie systemu

Tu będzie trochę inaczej. Jeżeli masz kilka rdzeni można poeksperymentować ze sposobem obsługi współbieżności przy starcie usług. W pliku /etc/init.d/rc należy odszukać linijkę CONCURRENCY=’none’ i zamienić ją na CONCURRENCY=’shell’. Spowoduje to, że usługi będą uruchamiane równolegle, a nie szeregowo. Może to doprowadzić do dość widowiskowego wyjebania się systemu łącznie z paniką jajka. Przyczyną może być zależność jakiś nietypowych usług. Odzyskiwanie… uruchomić z LiveCD lub w singlu i przywrócić pierwotną konfigurację. System wstaje rzeczywiście trochę szybciej.
Bardzo podobną metodą jest zmiana działania skryptu rc. No ale to jest dla hardkorów, którzy rozumieją jak on działa.