wtorek, 16 grudnia 2008

Optymalizacja operacji na danych w OpenBaseMovil-db

System zapisu danych w OpenBaseMovile-db podobnie jak RMS opiera się na schemacie otwierania i ich zamykania. Gdy chcemy wykonać jakieś operacje na danych zbiór odpowiadający tabeli (to samo indeksy) jest otwierany a gdy skończymy to zamykany. Dzieje się to automatycznie i wykonywane jest przez bibliotekę. Co ciekawe dany zbiór może być otwierany kilka razy i kilka razy zamykany. Używany jest do tego licznik, który pilnuje aby tylko za pierwszym razem otworzyć zbiór i zamknąć go wtedy gdy liczba zamknięć będzie odpowiadać liczbie otwarć. Można to wykorzystać do optymalizacji operacji na zbiorach. Jeśli pozostawiamy wszystko bibliotece, podczas np 300 insertów 300 razy wykonywana jest operacja otwierania i zamykania zbioru. Jeśli sami wcześniej otworzymy zbiór to wykona się to tylko raz i znacznie przyspieszy wprowadzanie danych.
Otwieranie zbioru wykonywane jest przez wywołanie operacji na tabeli openTree();.
Schemat:
try {
tabela.openTree();
// wstawianie danych
} finally {
tabela.closeTree();
}
I już jest znacznie wydajniej :) Tylko koniecznie trzeba pamiętać o zamknięciu zbioru!

niedziela, 14 grudnia 2008

Koty są dziwne...

Po prostu nie mogłem się powstrzymać przed umieszczeniem tego tutaj :)
Te kotki nigdy się nie poddadzą!

Genialne :)

Wykopane na Wykop.pl ;-)

Edit:
Dorzucę jeszcze to:

też wykopane ;-)

Koty są spoko ^^

czwartek, 11 grudnia 2008

Ułatwianie życia z JSF - PanelGrid

Zabrałem się za JSF! Nie miałem wcześniej żadnego doświadczenia z frameworkami javowymi to tworzenia www i każda strona książki Core JavaServer Faces coraz wyraźniej pokazuje mi, że byłem mocno zacofany ;)
Dziś np. miła niespodzianka w postaci znacznika panelGrid. Pisząc szablony w php strasznie wnerwiało mnie tworzenie tabel do formularzy (i nie tylko:>). Było to nużące i oszpecało kod.
A w JSF odkryłem znacznik panelGrid który tworzy sam tabele. Wystarczy podać liczbę kolumn a następnie wypisywać kolejne elementy.
Np.
<h:panelGrid columns="2">
<h:outputText value="Login:"/>
<h:inputText required="true"
value="#{userRegistrationBean.login}" />

<h:outputText value="Hasło:"/>
<h:inputSecret required="true"
value="#{userRegistrationBean.password}" />
</h:panelGrid>
I to wygeneruje taki kod HTML:
<table>
<tbody>
<tr>
<td>Login:</td>

<td><input type="text" name="j_id_id18:j_id_id64" value="" /></td>
</tr>
<tr>
<td>Hasło:</td>
<td><input type="password" name="j_id_id18:j_id_id68" value="" /></td>
</tr>
</tbody>
</table>

Oczywiście ten znacznik posiada sporo atrybutów dzięki którym można dostosować go do konkretnych potrzeb. Poczytać o nich można tutaj.

Jeśli w komórce ma się znaleźć więcej niż jeden znacznik należy użyć znacznika grupującego panelGroup.
Wracam do nauki...

czwartek, 4 grudnia 2008

Rejestracja na najbliższe spotkanie Poznań Java User Group

Na najbliższe spotkanie Poznańskiego JUGa należy się zarejestrować (chyba organizatorzy chcą wiedzieć ile będzie osób bo ostatnio się wszyscy nie mieścili w sali:P).
Rejestracja dostępna jest pod adresem http://oiola.com/e/252-spotkanie-poznan-jug-wicket-08122008/.
Spotkanie odbędzie się także 30min później niż wcześniej zapowiadałem.

Podsumowując:
Temat: Wicket
Prelegent: Stanisław Osiński
Miejsce: Siedziba Cognifide, Aleja Wielkopolska 4, Poznań
Data: 8.12.2008
Godzina: 18:30
Rejestracja: tutaj

Zapraszam!

Zmiana Look And Feel w NetBeans

Jeśli znudził Ci się standardowy look and feel NetBeans to wiedz, że można go łatwo podmienić ^^
Istnieją dwa sposoby:
- uruchomić NetBeans z parametrem
--laf [klasa L&F]

- lub dodać ten parametr do pliku [katalog z nb]/etc/netbeans.conf do netbeans_default_options.

Efekty:
--laf javax.swing.plaf.metal.MetalLookAndFeel

--laf com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel


A jeśli znudziły Ci się standardowe wyglądy, możesz uruchomić inny dodając do ścieżki odpowiednią bibliotekę:
--laf [klasa z L&F] -cp:p [ścieżka do JARa]

Osobiście jednak najbardziej jestem przekonany do standardowego wyglądu :P

ps. screeny są z RC2, bo w wersji finalnej mam za duży bałagan w projektach ;)

wtorek, 2 grudnia 2008

Klient web service w Java Micro Edition bez JSR-172

Przez ostatnie dwa dni walczyłem żeby podłączyć klienta web service w mojej aplikacji mobilnej. Na emulatorze wszystko śmigało aż miło ale testy na telefonie komórkowym nie powiodły się ponieważ moje telefony (SE K750i oraz Nokia 9300i) nie obsługują J2ME Web Services Specification (JSR-172), a kod generowanego klienta przez NetBeans właśnie na tej specyfikacji się opierał. To ogranicza liczbę urządzeń na których moja aplikacja będzie mogła działać.
Rozwiązania w mojej głowie pojawiły się dwa: albo zignorować i opierać wszystko na tej implementacji, albo ręcznie bawić się w parsowanie komunikatów SOAP (o zgrozo!).
Co prawda drugie rozwiązanie nie byłoby aż tak tragiczne ponieważ udało mi się znaleźć jakąś pomocną bibliotekę (kSOAP) no ale i tak nie jest tak fajnie jak powinno. Pozostając tymczasowo przy pierwszym (łatwo później podmienić takiego klienta) postanowiłem przepytać ludzi na pl.comp.lang.java czy nie mają jakiś pomysłów. Ostatecznie skontaktowałem się z Karolem Harezlakiem który podał mi rozwiązanie tego problemu.
Aby klient J2ME nie korzystał z JSR-172 należy użyć serwera proxy który będzie tłumaczył dane z web service na dane binarne których przetwarzaniem zajmie się już klient J2ME. Wszystko oczywiście łatwe i proste dzięki środowisku NetBeans IDE :)
Przejdźmy do praktycznych rzeczy:)

Web Service
Niech nasza usługa będzie super zaawansowaną usługą sieciową i niech jej zadaniem będzie mnożenie dwóch liczb :)
No to do roboty, tworzymy projekt new project -> Java EE -> EJB Module. Nazwa: MultiplyingService, w następnym oknie wybieramy serwer aplikacji na którym będzemy uruchamiać usługę, ja wybrałem GlassFisha V2 (instaluje się razem z NetBeans). Koniecznie wybieramy wersje Java EE 5.
Żeby wszystkiego nie generować i przy okazji liznąć trochę EJB napiszemy sami usługę.
Dodajemy nowa klasę javy do projektu o nazwie: MultiplyingWS.java
package com.blogspot.wookasz.j2mecwsclient;

import javax.ejb.Stateless;
import javax.jws.WebService;

@Stateless
@WebService
public class MultiplyingWS {
public int multiply(int a, int b) {
return a * b;
}
}
Adnotacja Stateless oznacza, że mamy do czynienia z bezstanowym komponentem sesyjnym, który wzbogacony o adnotację WebService stanie się usługą sieciową zdolną do komunikacji poprzez protokół SOAP. Generacją WSDLa i innymi szczegółami zajmuje się serwer aplikacji.
Wykonujemy deploy na serwer.

Servlet
Ok, teraz musimy stworzyć servlet który będzie jednoczenie klientem usługi oraz będzie udostępniał jego wyniki klientowi J2ME.
Tworzymy nowy projekt ProxyServlet: New project -> Java Web -> Web Application. Dodajemy do niego New File -> Web Services -> Web Service Client. Usługę dla niego wybieramy z poprzednio utworzonego projektu.

Wykonujemy deploy na serwer.

J2ME Client
No to został nasz ostatni docelowy klocek. Tworzymy nową aplikację J2ME New Project -> J2ME -> Mobile Application o nazwie WSClient, wybierająć CLDC 1.1 oraz MIDP 2.0.
Do projektu dodajemy New File -> MIDP -> Java ME Client to Web Application. I konfigurujemy go jak na obrazkach:



Klikamy finish i zostanie dodany po chwili do projektu plik o nazwie MultiplyWSClient.java który jest naszym docelowym klientem usługi sieciowej. Jeszcze utwórzmy głowny MIDlet WSClient.java:
package com.blogspot.wookasz.j2mewsclient;

import java.io.IOException;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.midlet.*;

public class WSClient extends MIDlet implements CommandListener {
public void startApp() {
try {
Form form = new Form("WebService Client");
int res = new MultiplyWSClient().multiply(2, 2);
String text = "2 * 2 = " + res;
form.append(text);
Command exitCmd = new Command("Wyjscie", Command.EXIT, 0);
form.addCommand(exitCmd);
form.setCommandListener(this);
Display display = Display.getDisplay(this);
display.setCurrent(form);

} catch (IOException ex) {
ex.printStackTrace();
}
}

public void pauseApp() {}

public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable d) {
notifyDestroyed();
}
}
I koniec! Jeśli wszystko wykonaliśmy poprawnie powinniśmy po odpaleniu emulatora otrzymać taki wynik:
Wszystko działa:) Testy na komórkach bez obsługi JSR-172 także wypadły pomyślnie!
Dziękuje bardzo Karolowi za pomoc!!

ps. dodam jeszcze, że całość została napisana na podstawie tutoriala: End-to-End Web Service Tutorial: Mobile Dilbert Application.

niedziela, 30 listopada 2008

Wicket na Poznań Java User Group.

W poniedziałek 8 grudnia odbędzie się kolejne spotkanie Poznań Java User Group. Na nim Pan Stanisław Osiński opowie nam o Wicket, czyli frameworku do tworzenia aplikacji webowych. Sam nie mam żadnego doświadczenia z tą biblioteką, więc mam nadzieję, że wykład będzie od podstaw :)
Miejsce to nowe centrum spotkań JUGowych - Cognifide na ulicy Aleje Niepodległości 4. Godzina prawdopodobnie 18:00.

Zapraszam !

Filtrowanie i sortowanie danych w OpenBaseMovil-db

Praca inżynierska wymaga ode mnie wykonania tych operacji w OpenBaseMovil-db no to przy okazji opiszę jak to się robi ;-)

Sortowanie
To będzie proste :)
Najpierw musimy pobrać jakiś zbiór danych, a następnie wykonań na nim metodę sort gdzie parametrami są:
String fieldName - kolumna po której sortujemy
int mode - rosnąco czy malejąco (RowSet.DESCENDING/RowSet.ASCENDING) - wartość domyślna to rosnąco.
Przykład:
RowSet firmy = Firmy.findAll();
firmy.sort("nazwa", RowSet.DESCENDING);
I to wszystko:) Przeglądając zbiór firmy będą one uszeregowane malejąco wg kolumny nazwa.

Filtrowanie
OpenBaseMovil-db ma niestety sporą wadę, nie można wyszukiwać danych które zawierają jakiś fragment tekstu (wyjątek - dana wartość zaczyna się od podanej sekwencji) dlatego zmuszeni jesteśmy do tworzenia własnych filtrów danych.
Aby tego dokonać musimy poprzez metodę RowSet.applyFilter przekazać obiekt implementujący interfejs RowFilter. Interfejs ten wymusza implementację metody matches(Row row) która zwraca wartość boolowską w zależności czy dany rekord ma zostać dołączony do wyniku czy nie.
Następnie możemy wykonać jedną z dwu operacji:
- RowSet.clearFilter() - aby anulować filtr i odzyskać początkowy zbiór
- RowSet.packFilter() - aby odrzucić wszystkie rekordy nie pasujące i dalej np. móc zastosować inny filtr.
Przykład:
RowSet set = stocks.findAll();
set.applyFilter(new RowFilter() {
public boolean matches(Row row) {
return row.getString("name").indexOf(name) == -1 ? false : true;
}
});
set.packFilter();
Wracam do pisania.... ;-)

środa, 19 listopada 2008

Jak sprawdzić czy baza danych istnieje w OpenBaseMovil-db

Po kilku dniach pracy z OpenBaseMovil-db natknąłem się na problem. Otóż operacja:
Database db = Database.connect(DATABASE_NAME);
jeśli baza danych nie istnieje to ją automatycznie utworzy. Lepsze to niż rzucać wyjątkiem ;-) No ale gdy później zaczynamy operować na tabelach które nie istnieją to wyjątek już się pojawia... Trzeba znaleźć sposób jak sprawdzić tabele zostały już utworzone podczas łączenia z bazą. Rozwiązanie odnalazło się na forum OpenBaseMovil. Sposobem na to jest jest wersjonowanie bazy przy użyciu metod Database.getVersionMajor() oraz Database.setVersionMajor().
Już spieszę z przykładem:
public Database createDb() {
Database dbh = null;
try {
dbh = Database.connect(DATABASE_NAME);
// 0 - tabele jeszcze nie istnieją
if (dbh.getVersionMajor() == 0) {
dbh.drop();
dbh = Database.create(DATABASE_NAME);
// tworzenie tabel
createTables(dbh);
// 1 - tabele utworzone
dbh.setVersionMajor((short) 1);
}
} catch (Exception e) {
dbh = null;
}
return dbh;
}
I problem rozwiązany :)

ps. wersja finalna NetBeans 6.5 dostępna tutaj :)

EDIT:
Metoda ostatecznie nie działała jak powinna, poprawiłem - teraz jest ok :)

wtorek, 18 listopada 2008

Eclipse DemoCamp już za tydzień!

Dziwna sprawa, dopiero teraz dowiedziałem się, że za tydzień w poniedziałek (24 listopada) odbędzie się kolejny w tym roku Eclipse DemoCamp w Poznaniu! Oczywiście już poprosiłem o dopisanie mnie do listy uczestników. Co prawda Eclipsa nie używam za często ale na takie niezwykle ciekawe spotkanie muszę się wybrać.
Pisząc niezwykle ciekawe wcale nie przesadzam, ponieważ zaproszono specjalnego gościa prosto z Kanady! Wassim Melhem - lider technicznego zespołu tworzącego Eclipse Plug-in Development Environment przyleci specjalnie do Poznania by opowiedzieć nam o swoich doświadczeniach z Eclipsem. Ponadto wystąpi też Dawid Weiss z PP (po Jego ostatnim wykładzie na PJUG już wiem, że będzie ciekawie;) oraz Bartosz Michalik z Eclipse Support Center.
Organizatorzy tak jak ostatnim razem organizują tzw lighting talks - czyli: chcesz opowiedzieć o swoich doświadczeniach z Eclipse ? Wstajesz i mówisz:)
Nie obędzie się też bez gratisowego piwka oraz pizzy :) (to myślę wszystkich przekona, żeby przyjść:P).

Zarejestrować się można tutaj.
A przybyć trzeba do klubu Piwnica 21 na ulicy Wielkiej 21 na godzinę 18:00 - czyli tak jak ostatnio.
Dla niewiedzących mapka:

Wyświetl większą mapę

ZAPRASZAM !

sobota, 15 listopada 2008

OpenBaseMovil-db czyli baza danych na komórki !

Czasu ostatnio mało... nie, ja zawsze cierpię na brak czasu! No ale nic z tym nie mogę zrobić. Szkoła, praca, praca inżynierska i na dodatek zapisałem się na kurs przygotowujący do certyfikatu z DB2 - DB2 9 Family Fundamentals. Baza danych dość ciekawa. Po wykonaniu pierwszych ćwiczeń znam więcej poleceń z konsoli niż z reszty baz danych jakie używałem łącznie. No ale nie o tym miałem pisać...

Wracamy do tematyki J2ME! Skoro wiemy już jak zapisywać dane w RMS i wiemy, że jest to bardzo niewygodne trzeba użyć czegoś z "jajami"!
OpenBaseMovil to właśnie taki framework. Jego część nazywająca się OpenBaseMovil-db to nic innego jak baza danych na urządzenia mobilne. Co prawda nie możemy używać SQLa i innych fajerwerków z nim związanych ale to nic! I tak użycie tej biblioteki w OGROMNYM stopniu ułatwi nam zarządzanie danymi w aplikacjach.

OpenBaseMovil-db jest relacyjną bazą danych napisaną w Javie na urządzenia obsługujące Jave (Java ME). Twórcy zadbali o to by była obsługiwana przez wszystkie urządzenia niezależnie od modelu czy wersji oprogramowania (przynajmniej tak jest napisane w dokumentacji;P). Wielkość bazy danych, tabeli, wiersza jest ograniczona tylko poprzez wielkość dostępnej pamięci.

Zacznijmy od bibliotek które są wymagane w classpath projektu. Oto lista:

Trochę ich sporo ale funkcjonalność nam to wynagradza:)

No to już możemy przejść do tworzenia bazy:
Database db = Database.create("TestDB");
db.start();
To chyba nie trzeba wyjaśnień.
Aby dodać przykładową tabelę z polami np id oraz imię wykonujemy polecenie
Table newTable = new Table("Names");

newTable.addColumn("id", Constants.FT_INT);
newTable.addColumn("name", Constants.FT_STRING, 20); // 20 oznacza długość pola
// tworzymy indeks na polu id
newTable.createIndex("main_index", "id");

db.createTable(newTable);

Co do nazwy tabeli to należy pamiętać, że musi być ona niepowtarzalna w obrębie wszystkich baz danych. Dość spore ograniczenie ale kto będzie miał w aplikacji na komórce wiele baz danych?!

Aby dodać jakiś wiersz należy utworzyć obiekt typu Row z odpowiedniej tabeli:
Row row = newTable.createRow();
row.setField("id", new Integer(1)); // można także row.setField("id", "1");
row.setField("name", "Duke");
row.save(); // Można także newTable.save(row);
No i mamy dane w bazie:)

Wyszukiwanie i przegląd tego co się znalazło wykonuje się następująco:
RowSet rows = newTable.find("id", new Integer(1));
while (rows.next()) {
System.out.println( rows.getCurrent().getString("name") );
}
Tyle chciałem przedstawić jako szybki i praktyczny wstęp do biblioteki. Oczywiście to nie wszystko! Zachęcam do przeczytania OpenBaseMovil-db-DeveloperGuide-3.0.02.pdf oraz do zaglądania tutaj bo z pewnością to nie pierwszy wpis na ten temat ;-)
No to wracam do pisania inżynierki...

niedziela, 9 listopada 2008

CentrumPaliw.pl


Chciałbym zapoczątkować drobny czyn społeczny u każdego z Was. Pomoże oszczędzić trochę $$ kierowcom. Polecam serwis CentrumPaliw.pl i zachęcam do wprowadzania do niego cen. Zajmuje to dosłownie moment a może pomóc w wyborze miejsca następnego tankowania. Serwis już trochę czasu funkcjonuje, posiada w bazie ponad 3400 stacji w całej Polsce. Kuleje trochę rejon Poznania który obserwuję. Serwis cierpi z powodu słabego rozreklamowania co chciałbym naprawić.
W niedługim czasie ma się pojawić wersja na urządzenia mobilne, umożliwi to wyszukanie najtańszej stacji prosto z komórki.

Podawajcie linka dalej!! ;-)

środa, 5 listopada 2008

LINQ w Javie ??

W Berlinie na spotkaniu grupy Object Database Technology Working Group padła propozycja aby dodać LINQ do języka Java jako standardowe API zapytań. Na spotkaniu najpierw porównano LINQ z konkurencyjnym rozwiązaniem SBQL i to LINQ wygrało pojedynek i być może zostanie wzięte pod lupę przez JCP i trafi do języka Java. Oczywiście będzie konieczna zmiana nazwy i zapewne kilka innych zmian ponieważ LINQ jest zastrzeżoną nazwą firmy Microsoft.

Co z tego będzie - nie wiem. Nie znam się na LINQ ale Java ma już swoje EJBQL i może lepiej byłoby rozbudować ten język zapytań niż dodawać kolejny klocek do Javy ? Będę czekał na nowe wiadomości w sieci na ten temat.

Link: LINQ is the best option for a future Java query API - ODBMS Industry Watch.

poniedziałek, 3 listopada 2008

Map reduce, Hadoop oraz co nowego w Java 1.6 update 10 na Poznań JUG

Już za dwa dni kolejne spotkanie JUG Poznań. Tym razem dowiemy się czegoś o tym jak przetwarzać ogromne ilości danych w teorii i praktyce. Opowie nam o tym Pan Dawid Weiss pracujący na Politechnice Poznańskiej. Przed samą prezentacją czeka nas jeszcze krótkie (ok. 15min.) wystąpienie Pana Tomasza Parkoły (PCSS) który opowie co nowego w Java 1.6 update 10.

Spotkanie odbędzie się 5 listopada (środa) o godzinie 18:00 w siedzibie Cognifide ul. Aleje Wielkopolskie 4.
Więcej szczegółów na stronie Poznań JUG.
Zapraszam!

niedziela, 2 listopada 2008

No more Zend Studio.... NetBeans incoming !

Od kilku dni testuję NetBeans w kobinacji z PHP. Przeniosłem do niego mój projekt z pracy. Wcześniej korzystałem z Zend Studio 5.5 którego mam już serdecznie dość! Wersja 6.0 zrobiona na Eclipsie mnie nie przekonała, jakoś nie mogłem się w niej odnaleźć, zwłaszcza korzystając z SVN. No a że w moim ulubionym środowisku ukazała się funkcjonalność której poszukiwałem no to nie mogłem sobie odmówić przyjemności testowania.
Krótko wypisałem zalety i wady który przez te kilka dni zauważyłem.

Zalety:
- todo list (jednak boję się na nią zaglądać, bo ciągle rośnie a nie maleje).
- filtry w todo list - świetne! Bardzo się przydają:)
- wstawianie elementów HTML z palety komponentów
- wskazuje zmiany w pliku jeśli korzystamy z systemu do wersjonowania już w trakcie edycji kodu
- znajduje błędy w HTMLu
- NetBeans jakoś wygląda ;P
- nie muszę się przełączać na inne środowisko żeby pisać coś w Javie
- możliwość pisania samemu wtyczek
- trochę bardziej inteligentne auto uzupełnianie. Np. gdy auto uzupełniałem __construct() automatycznie zostałem przeniesiony do nowej linii, dodane zostały klamry a także znak ; za pozycją kursora. Inne: gdy dane wyrażenie pasuje tylko do jednej metody/zmiennej to automatycznie jest wstawiane, nie trzeba wybierać z jedno elementowej listy
- ładniejsze czcionki i kolorowanie składni (wiem, że to można zmieniać ale leniwy jestem :P)
- podpowiadanie składni czasami pokazuje funkcje jakby były przeciążane. Dzieje się tak gdy parametry funkcji mogą przyjąć wartość domyślną.
- wsparcie dla javascript - nareszcie !!
- dedukcja typu zmienne na podstawie phpdoca (to akurat też miał ZF ale bez tego jak bez ręki)
- nowość w 6.5 RC1 - Quick Search oczywiście także obsługuje źródła PHP

Wady:
- wydajność todo list. Mogłoby być jakieś cachowanie a nie co uruchomienie NetBeans sprawdza cały projekt. Mam kilka set plików w projekcie i trochę to trwa (na szczęście zawsze hibernuję komputer, więc tego nie odczuwam za bardzo)
- usunięcie pliku z projektu = usunięcie pliku z SVN. Nie podoba mi się to z tego względu, że trzymam kilka plików które służą mi do testów a nie należą bezpośrednio do projektu. Można to obejść przez 'ignore' dla pliku ale dla plików już istniejących trzeba chwilę poklikać.
- nie ma wsparcia dla phpdoc ? Nie znalazłem jak dotąd
- chyba coś nie działają bookmarki ;/
- no i największy minus - cała zakładka refactor nie działa dla plików PHP;/ Mam nadzieje, że to zostanie dodane w wersji finalnej, bo bez tego nie można po prostu żyć;/

Ogólnie patrząc to zalety odnoszą się do całego IDE NetBeans a nie tylko do obsługi PHP :P No ale brakowało mi kilku tych funkcji w zendzie. Oczywiście, już nie wrócę do niego (chyba, że kolejne podejście do wersji Eclipsowej mnie przekona do siebie), nie mogę już na niego patrzeć. Na tę chwilę najbardziej mi brakuje tego refaktoringu kodu;/ Ta opcja jest dla mnie najważniejsza i musi się pojawić w wersji finalnej.

NetBeans <3

środa, 29 października 2008

Why EJB 3.x rox by Adam Bien

Adam Bien opublikował wczoraj artykuł w serwisie javaworld.com na temat EJB 3. Zawarł w nim swój punkt widzenia dlaczego lubi EJB, wyjaśnia jakie były jego bolączki i jak zostały one sprawnie rozwiązane w najnowszym wydaniu (największa radość jest chyba z braku konieczności pisania setek linii w XMLu aby skonfigurować aplikację). Wspomina także o Java Persistence, wstrzykiwaniu zależności oraz zasobów. Najwięcej miejsca jednak poświęcił interceptorom (metody przechwytujące), opisał sposób ich definiowania oraz możliwe wykorzystanie. Cały artykuł przy tym jest bogato zdobiony przykładami.
Polecam się z nim zapoznać ;-)

EJB3 : From Legacy technology to secret weapon
Adam Bien's Weblog

wtorek, 28 października 2008

Uzyskanie dostępu do EntityManager z poziomu Java SE

Z JPA możemy korzystać nie tylko na serwerze aplikacyjnym ale także w aplikacjach desktopoych w poczciwym Java SE. Jednak aby tego dokonać nie możemy użyć wstrzykiwania tylko musimy skorzystać z klasy javax.persistence.Persistence aby za pomocą metody createEntityManagerFactory utworzyć obiekt typu EntityManagerFactory. Metoda przyjmuje jeden lub dwa parametry. Pierwszy to String - nazwa jednostki utrwalania z której będziemy korzystać, zdefiniowana musi być ona w pliku persistence.xml. Dodatkowo jeśli chcemy zmodyfikować właściwości jakie w nim zostały ustalone możemy podać obiekt typu Map jako drugi parametr i w zawrzeć ustawienia jakie nam odpowiadają.
EntityManagerFactory umożliwia nam utworzenie potrzebnego nam kontekstu utrwalania EntityManager za pomocą metody createEntityManager().

Po zakończeniu korzystania z EntityManagerFactory dobrze jest zamknąć i zwolnić zasoby poprzez wywołanie metody close().

Ok, no to teraz przykład:
JPATest.java
package com.blogspot.wookasz.jpainj2se;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JPATest {

public static void main(String[] args) {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPAJ2SETestPU");
EntityManager entityManager = factory.createEntityManager();
factory.close();

Person person = new Person(1L, "Zbyszko", "Ul. Nieznana 18");
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(person);
transaction.commit();
}
}
Person.java
package com.blogspot.wookasz.jpainj2se;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Person implements Serializable {

@Id
private Long id;

private String name;
private String address;

public Person() {
}

public Person(Long id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

}
persistence.xml



org.hibernate.ejb.HibernatePersistence
com.blogspot.wookasz.jpainj2se.Person








Koniecznie trzeba jeszcze dołączyć Hibernate (lub TopLink ale wtedy trzeba zmodyfikować plik xml) do projektu oraz sterownik odpowiadający używanej bazie danych.

Należy też pamiętać, że jeśli podczas tworzenia EntityManagera aktywna była transakcja to musimy wykonać na nim metoda joinTransaction() aby się do niej przyłączyć, w przeciwnym wypadku dane nie będą synchronizowane z bazą danych.

niedziela, 26 października 2008

Po NetBeans day Poznań

Wczoraj odbył się zapowiadany przeze mnie (i nie tylko) NetBeans Day na Uniwersytecie Adama Mickiewicza w Poznaniu.
Dotarłem na miejsce bezpiecznie ok 9:30. Rejestracją zajmował się Adam Dudczak - bardzo aktywny członek JUG Poznań, z którym się przy okazji zapoznałem (bardzo pozytywna osoba;).
Po pół godzinie czekania (+10min na drobne problemy techniczne) i pierwsze wystąpienie rozpoczął Geertjan Wielenga, technical writer w firmie Sun. Temat: “Creating an application on the NetBeans Platform”. Geertjan przedstawił problemy techniczne jakie napotykają podczas tworzenia NetBeans a następnie przeszedł do omówienia NetBeans Platform jako platformy to budowania aplikacji desktopowych. Pokazał główną zaletę - modularność, zarysował API platformy oraz pokazał którkie demo jak w prosty sposób przenieść już istniejącą aplikację na platformę NetBeans. Jak później się okazało Geertjan Wielenga jest takim Guru NetBeans:) Praktycznie wie o wszystkim co jest w tym środowisku ^^

Następne wystąpienie pt: “Programowanie w oparciu o platformę Netbeans w praktyce, czyli problemy, konstrukcje warte uwagi oraz skąd i jak czerpać na ten temat wiedzę” poprowadził Adam Kędziora - prezes koła naukowego na UAMie. Wystąpienie poświęcone problemom z jakimi spotkał się Adam podczas tworzenia wizualnego edytora JavaFX na jeden z konkursów. Na końcu podał też przydatne źródła wiedzy dla osób tworzących aplikacje w NetBeans Platform.
Godzina 12 wybiła - 20 minutowa przerwa:) Organizatorzy po wyjściu z sali przygotowali dla nas drobny poczęstunek w postaci góry ciastek i kartonów z sokiem.

Przerwa minęła - Adam Dudczak - “VisualVM i VisualVM API”, czyli temat który przegapiłem na PJUGu. Polecam to narzędzie! Bardzo bogata funkcjonalność, która przyda się praktycznie zawsze gdy w naszej aplikacji coś się sypie i nie wiadomo gdzie. Narzędzie dostępne razem z JDK:) Na końcu Adam pokazał jak tworzyć własne wtyczki do VisualVM - bardzo prosta sprawa:) Nawet prosta strzelankę można zrobić :P

O 13 wykład na który czekałem. Autor wizualnego edytora NetBeans Mobility Karol Harezlak mówił o "Teraźniejszości i przyszłości Javowych technologi mobilnych - NetBeans Mobility". Pokazał demo (i to nie jedno;), zapowiedział, że w przyszłym roku pojawi się wersja JavaFX na urządzenia mobilne oraz nowa wersja MIDP (3.0). Po prezentacji udało mi się kilka słów z Karolem wymienić nt. mojej inżynierki, trochę pomógł :) Miło było poznać osobę której narzędzia używa się na co dzień :)

Kolejna przerwa - tym razem obiadowa. Po niej Toni Epple z tematem “Porting an application to the NetBeans Platform”. Toni w swojej pracy przenosił aplikację napisaną we własnym frameworku na platformę NetBeans, przyjechał na spotkanie aby opowiedzieć o tym i podzielić się doświadczeniem jakie podczas tego zadania nabył. Także pokazał (podobnie jak Geertjan) demo jak w prosty sposób można wykonać taki "transfer aplikacji" - zrobiło wrażenie. Dobrze napisana aplikacja jest niezwykle łatwa w przeniesieniu.

No i na samym końcu prezentacja która mi się najbardziej podobała (może dlatego, że było o JEE ?:P). Adam Bien przedstawił “NetBeans and Glassfish - the Synergy for Pragmatic Java EE 6 development” - wszystko na NetBeans 6.5 RC1 którego używał zaledwie przed 3 dni ("No risk, no fun"). Musze przyznać, że poziom obsługi tego środowiska przez Adama jest imponujący. W bardzo szybki sposób zbudował aplikację uzywająć EJB, JPA, JSF, JMS i serwletów - wszystko w NetBeans 6.5 RC1 i GlassFish:) Bardzo podobała mi się ta prezentacja:) Na blogu Adama Biena można przeczytać już wpis o niej z jego perspektywy.

Na koniec organizatorzy rozlosowali nagrody dla zwycięzców konkursu w którym można było wziąć udział w miedzy czasie. Należało odpowiedzieć na kilka pytań - ja poległem, nie znam się na apletach, swingu i historii NetBeans:P

Na imprezie zabrakło niestety Jacka Laskowskiego którego bardzo chciałem poznać :( Tak się złożyło, że nie przyjechał ze swoją prezentacją o zaawansowanym EJB w NetBeans. Ale za to obiecał udostępnić ją w internecie. Przedstawił ją dzisiaj na Gdańskim NetBeans Day.

Wnioski końcowe:
- zainstalować wersję 6.5 RC1
- potestować NetBeans Platform
- zapoznać się bliżej z VisualVM
- jeśli kiedyś bym chciał też wystąpić na takim evencie prawdopodobnie musiałbym zmienić imię na Adam ;P

czwartek, 23 października 2008

NetBeans 6.5 Release Candidate 1 dostępny do ściągnięcia


Od dwóch dni można pobierać wersje RC1 środowiska NetBeans 6.5.
Nowa wersja środowiska wprowadza wiele poprawek, udogodnień, funkcji. Między innymi:
- wsparcie dla języka PHP, JavaScript, Ajax
- debugger JavaScript dla Firefox i IE
- wsparcie dla Groovy i Grails
- ulepszony edytor C++
- nowy kreator dodawania nowych komponentów dla aplikacji mobilnych
- poprawki w debuggerze
i wiele innych o których można poczytać na stronie www.NetBeans.org.

Chciałem jeszcze przypomnieć o sobotnim i niedzielnym NetBeans Day w Poznaniu i Gdańsku -> NetBeansDay.pl. Znany jest już harmonogram wykładów z którym można zapoznać się tutaj.
Kto się jeszcze nie zarejestrował niech to szybko uczyni ;-)
Zapraszam!

poniedziałek, 20 października 2008

Rozsyłanie sygnałów w JMX

Kontynuujemy zabawę z JMX :) W poprzednim wpisie stworzyliśmy aplikację która umożliwiała zmianę parametrów mziaren 'na odległość'. W tym poście wzbogacimy ją o funkcję rozsyłania sygnałów przy spełnieniu pewnych warunków - u nas będzie to sygnał o przekroczenie limitu użytkowników.
Kody źródłowe z poprzedniego wpisu można pobrać: tutaj (projekty w NetBeans IDE).

Zacznijmy od tego jak reprezentowany jest sygnał. Kiedy go wysyłamy przesyłany jest obiekt typu javax.management.Notification, któremu w konstruktorze możemy podać takie parametry jak typ(String), źródło(Object), numer sygnału(long), czas (long) oraz wiadomość (String).

MBean który chce wysyłać sygnały musi implementować interfejs NotificationEmitter jednak w praktyce klasa ziarna dziedziczy po klasie NotificationBroadcasterSupport, która udostępnia kilka użytecznych metod - właśnie tej klasy użyjemy w przykładzie.
No to przejdźmy do implementacji...

Serwer
Lista modyfikacji które należy wprowadzić w klasie serwera:
- klasa powinna dziedziczyć po javax.management.NotificationBroadcasterSupport
- dodajemy pole:
private static final String TYPE_LIMIT_USERS = "USERS_SERVER_LIMIT";
będzie to nasz typ komunikatu. Można to zrealizować trochę inaczej tworząc podklasę klasy Notification i w niej opakować takie informację (przykładem takiej klasy jest np. AttributeChangeNotification).
- dodajemy pole
private int notifyCounter = 0;
które będzie licznikiem wysyłanych sygnałów.

W konstruktorze klasy dodamy klasę anonimową (wątek) która będzie sprawdzać co określony okres czasu czy przekroczono maksymalną liczbę użytkowników. Jeśli taka sytuacja nastąpi wysłany zostanie sygnał do wszystkich "słuchaczy" - czyli klientów obserwujących to mziarno.

Wysłanie sygnału odbywa się poprzez wywołanie metody sendNotification którą odziedziczyliśmy.

W kodzie pojawia się dodatkowy wątek który dla testów zmienia wartość users na większy niż limit aby przetestować działanie całości.

Oto kompletny kod Server.java:
package com.blogspot.wookasz.jmxtutorial;

import java.util.Random;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;

public class Server extends NotificationBroadcasterSupport
implements ServerMBean {

private static final String TYPE_LIMIT_USERS = "USERS_SERVER_LIMIT";
private int notifyCounter = 0;
private int users = 0;
private int limit = 5;
private Thread notificationThread;

public Server() {
Random rnd = new Random();
users = rnd.nextInt(100);

final Server serverObj = this;

notificationThread = new Thread() {

@Override
public void run() {
try {
while (!Thread.interrupted()) {
Thread.sleep(1000 * 10);
System.out.println("Sprawdzanie");
if (limit < users) {
Notification notify =
new Notification(TYPE_LIMIT_USERS,
serverObj,
++notifyCounter,
System.currentTimeMillis(),
"Przekroczono dopuszczalny limit użytkowników na serwerze");
System.out.println("Wysyłanie");
sendNotification(notify);
}
}
} catch (InterruptedException ex) {
}
}
};
notificationThread.start();

/****************************************/
// wątek potrzebny do przykładu
Thread test = new Thread() {

@Override
public void run() {
try {
Thread.sleep(100);
System.out.println("Zmiana");
users = limit + 1;
} catch (InterruptedException ex) {
}
}
};
test.start();
}

public void setUsersLimit(int limit) {
this.limit = limit;
System.out.println("Limit uzytkowników zmieniono na: " + limit);
}

public int getUsers() {
return users;
}
}

Reszta plików pozostaje bez zmian.

Klient
Klasa klienta aby mogła odebrać sygnał musi implementować interfejs NotificationListener który wymusza implementację metody handleNotification.
Parametrami tej metody są:
- Notification notification - sygnał przychodzący
- Object handback - obiekt przekazywany w trakcie wywoływania metody addListener - rejestrowania słuchacza. Jest to obiekt pomocniczy.
Po zaimplementowaniu obiektu nasłuchującego należy go zarejestrować wywołując metodę addNotificationListener klasy typu MBeanServerConnection.
Metoda ta przyjmuje następujące parametry:
- ObjectName name - nazwa mziarna które emituje sygnały
- NotifiactionListener listener - obiekt nasłuchujący który rejestrujemy
- NotificationFilter - filtr sygnałów
- Object handback - obiekt pomocniczy przekazywany do obiektu nasłuchującego

No i to by było na tyle :)
Kod klasy nasłuchującej ClientListener.java:
package com.blogspot.wookasz.jmxtutorial;

import java.util.Date;
import javax.management.*;

public class ClientListener implements NotificationListener {

public void handleNotification(Notification notification,
Object handback) {

System.out.println("*** Odebrano sygnał! ****");
System.out.println("Wiadomość: " + notification.getMessage());
System.out.println("Nadany o godzinie: " + new Date(notification.getTimeStamp()));
}
}

Do klasy klienta dodano tylko następujące linie rejestrujące obiekt nasłuchujący:
ClientListener listener = new ClientListener();
server.addNotificationListener(name, listener, null, null);

Pełne kody źródłowe można pobrać: tutaj.

Zapraszam do komentowania ;-)

środa, 8 października 2008

Pierwsze kroki z JMX

JMX - czyli Java Management Extensions, to kolejna technologia javowa z którą przyszło mi się spotkać i zainteresować. Dziś mały wstęp do tej technologii i może "krótki" przykład ;-)

JMX jak Wikipedia nam tłumaczy jest technologią Javy, która zawiera narzędzia potrzebne do zarządzania oraz monitorowania aplikacji, urządzeń, usług zorientowanych sieciowo.
A teraz kilka pojęć i informacji wstępnych:
Ziarno zarządzane - m-ziarno - mbean - jest to obiekt Javy którym można zarządzać. Taki obiekt posiada atrybuty, operacje oraz sygnały. O ile atrybuty i operacje są dość oczywiste to sygnały są obiektami pewnych klas, które przy spełnieniu pewnych warunków mziarno może rozsyłać do słuchaczy.
M-ziarno musi implementować interfejs zarządzania - m-interfejs, który określa jakie właściwości posiada m-ziarno i jakie operacje na nim można wykonywać w aplikacji. Sygnałów nie uwzględniamy w interfejsie, a atrybuty są deklarowane przez metody set/get.
Interfejs oraz klasa mziarna muszą być publiczne.
Teraz ważna kwestia nazewnictwa. Nazwa klasy m-ziarna, natomiast m-interfejs musi przyjmować nazwę [nazwa klasy]MBean. Czyli, jeśli nasza klasa ma nazwę Ship, to interfejs który implementuje musi się nazywać ShipMBean. Co do nazewnictwa metod get/set to są one takie same jak w przypadku JavaBeans.

To chyba tyle z teoretycznych podstaw, reszta wyjdzie w praniu ;-)

Rejestrowanie m-ziarna
Żeby skorzystać z m-ziarna należy je wcześniej zarejestrować w serwerze m-ziaren. Domyślnie każda JVM przechowuje systemowy serwer m-ziaren i do niego będziemy dorzucać nasze ziarenka.
Obiekt serwera zwraca nam metoda (statyczna)
MBeanServer ManagementFactory.getPlatformMBeanServer()


Zanim jednak dodamy do niego nasz obiekt należy go wcześniej opakować tak, żeby był łatwiejszy do wyszukania na serwerze. Dokonujemy tego poprzez utworzenie dla niego nazwy, a dokładniej obiektu: ObjectName. Konstruktor przyjmuje 3 parametry:
- String domena - my będziemy używać domeny domyślnej dla serwera m-ziaren
- String klucz
- String wartosc
Ostatnie dwa parametry służą określenia nazwy m-ziarna, które może nam sugerować jego przeznaczenie.

Teraz możemy zarejestrować mbean (zakładamy że Test to klasa naszego ziarna:
Test mbean = new Test();

MBeanServer server = ManagementFactory.getPlatformMBeanServer();

ObjectName name = new ObjectName(server.getDefaultDomain(),
"JMXLearning",
"TestBean");

ObjectInstance mbeanObj = server.registerMBean(mbean, name);

mbeanObj przechowuje informacje o zarejestrowanym ziarnie.
Ok, mamy zarejestrowany obiekt. Możemy teraz odpalić naszą aplikacje. Uruchamianie wymaga podania maszynie wirtualnej javy następujących parametrów:
-Dcom.sun.management.jmxremote.port=[numer portu] - numer portu na którym nasłuchiwać będziemy na sygnały
-Dcom.sun.management.jmxremote.authenticate=[true/false] - czy ma być przeprowadzona autoryzacja
-Dcom.sun.management.jmxremote.ssl=[true/false] - czy używać bezpiecznego protokołu ssl
To by było na tyle z części "serwerowej". Teraz czas na klienta.

Dostęp do m-ziaren
Żeby wykonać jakieś operacje na m-ziarnach trzeba najpierw znać adres serwera na którym są one udostępnione. Adres taki ma postać:
service:jmx:rmi:///jndi/rmi://[nazwa hosta]:[numer portu]/jmxrmi

i reprezentowany jest przez obiekt typu JMXServiceURL. Jego konstruktor przyjmuje jako parametr String z adresem postaci takiej jak powyżej.
Połączenie z m-serwerem uzyskuje się następująco:
JMXConnector con = JMXConnectorFactory.connect(url);
MBeanServerConnection server = con.getMBeanServerConnection();

Poprzez obiekt łącznika JMXConnector otrzymujemy połączenie z m-serwerem który reprezentowany jest przez obiekt typu MBeanServerConnection.
W tym momencie jeśli nie znamy m-interfejsu ziarna na serwerze to możemy pobierać odpowiednie wartości poprzez metodę getAttribute lub przypisywać je poprzez odpowiednio setAttribute.
Jeśli znamy m-intefejs to możemy pobrać zdalną referencje na m-ziarno i wykonywać na nim operacje tak jakby był do niego dostęp bezpośredni w aplikacji. Aby tego dokonać należy wywołać statyczną metodę klasy MBeanServerInvocationHandler o nazwie getProxyInstance.
Przyjmuje ona 4 parametry, odpowiednio:
MBeanServerConnection connection - połączenie z serwerem
ObjectName objectName - reprezentacja nazwy obiektu m-ziarna
Class interfaceClass - interfejs implementowany przez m-ziarno
boolean notificationBroadcaster - czy pośrednik (czyli obiekt który otrzymamy) ma informować o sygnałach emitowanych przez m-ziarno
Przykład:
ShipMBean mbean = (ShipMBean)MBeanServerInvocationHandler.
newProxyInstance(server,
name,
ShipMBean.class,
false);
Teraz wykonując operacje na obiekcie mbean wykonujemy zdalnie operacje na m-ziarnie na serwerze.
To wszystko z teorii :) Poniżej zamieszczam kompletny kod źródłowy przykładowej aplikacji dzięki której będzie można pobierać informacje o liczbie użytkowników podłączonych do serwera oraz ustalać ich limit.

M-Interfejs - ServerMBean.java
package com.blogspot.wookasz.jmxtutorial;

public interface ServerMBean {
public void setUsersLimit(int limit);
public int getUsers();
}
M-Ziarno - Server.java
package com.blogspot.wookasz.jmxtutorial;

import java.util.Random;

public class Server implements ServerMBean {
private int limit = 100;
private int users = 0;

public Server() {
Random rnd = new Random();
users = rnd.nextInt(100);
}

public void setUsersLimit(int limit) {
this.limit = limit;
System.out.println("Limit uzytkowników zmieniono na: " + limit);
}

public int getUsers() {
return users;
}
}
Rejestracja m-ziarna - ServerRegistration.java
package com.blogspot.wookasz.jmxtutorial;

import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;

public class ServerRegistration {

public static void main(String[] args) {
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName(server.getDefaultDomain(), "tutorial", "server");
Server mbean = new Server();
server.registerMBean(mbean, name);

Thread.sleep(Long.MAX_VALUE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Uruchamiamy ten plik z parametrami:
-Dcom.sun.management.jmxremote.port=2005
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

I program klienta - Client.java
package com.blogspot.wookasz.jmxtutorial;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class Client {

public static final String servelUrl = "service:jmx:rmi:///jndi/rmi://localhost:2005/jmxrmi";

public static void main(String[] args) {
new Client().doTest();
}

public void doTest() {
try {
JMXServiceURL url = new JMXServiceURL(servelUrl);

JMXConnector con = JMXConnectorFactory.connect(url);
MBeanServerConnection server = con.getMBeanServerConnection();
ObjectName name = new ObjectName(server.getDefaultDomain(),
"tutorial", "server");

ServerMBean mbean = (ServerMBean)MBeanServerInvocationHandler.
newProxyInstance(server,
name,
ServerMBean.class,
false);

System.out.println("Liczba użytkowników na serwerze: " + mbean.getUsers());
mbean.setUsersLimit(120);
} catch(Exception e) {
e.printStackTrace();
}
}
}

Kompletne kody źródłowe można pobrać tutaj (projekty w NetBeans).

Zapraszam do komentowania ;-)

ps. zna ktoś plugina do bloggera, żeby dzielić posty ? Tzn. całość postu żeby pojawiała się po wybraniu czytaj dalej jak np w wordpress.

wtorek, 7 października 2008

Pokaz możliwości Java Real-Time System

Robi wrażenie. Nie sądziłem, że Java takiemu zadaniu podoła, a tu widzę, że bez problemu :)


niedziela, 28 września 2008

NetBeans day i pierwsze powakacyjne spotkanie Poznań JUG

Może najpierw zacznę od NetBeans World Tour z okazji których odbędą się spotkania w Poznaniu (25 października) oraz Gdańsku (26 października). Serdecznie zapraszam do rejestracji gdyż przedstawionych będzie wiele nowości w NetBeans 6.5 oraz pojawią się takie osobistości jak: Adam Bien, Toni Epple, Jacek Laskowski, Geertjan Wielenga. Więcej szczegółów oraz rejestracja na polskiej stronie NetBeansWordTour - www.netbeansday.pl.

A już za kilka dni, bo 1 października odbędzie się pierwsze powakacyjne spotkanie Poznańskiej Grupy Użytkowników Javy !:) Tematem będzie Visual VM, JMX i jeszcze kilka rzeczy, a przedstawi to wszystko Adam Dudczak. Spotkanie rozpocznie się o godzinie 18:00 w budynku przy ulicy Zwierzynieckiej 20 - sala nr 4. Więcej szczegółów w newsie na stronie Poznańskiego JUGa

Na oba spotkania serdecznie zapraszam !

środa, 24 września 2008

"Break" time

Trzeba pozaliczać kilka rzeczy podczas kampanii wrześniowej na uczelni, więc nie mam za bardzo czasu żeby coś napisać (chociaż kilka artów czeka w poczekalni już :P).

Na pocieszenie trochę humoru ;-)


sobota, 13 września 2008

Co nowego w Java 7 ?

Szperałem sobie ostatnio po internecie w poszukiwaniu informacji o Javie i jej rozwoju natrafiłem na blog Alexa Millera w którym opisał proponowane nowości w Java 7.
Postaram kilka z nich tutaj przybliżyć ale proszę pamiętać, że wszystko jest nieoficjalne i to tylko propozycje !

Wnioskowanie typu
Kompilator będzie wnioskować typ podczas tworzenia obiektów generycznych. Zapis:
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
może być zastąpiony przez:
Map<String, List<String>> anagrams = new HashMap<>();
Ta zmiana zdecydowanie potrzebna. Wyeliminuje te tasiemce w kodzie:)

String w konstrukcji switch
Tutaj chyba nie trzeba za wiele tłumaczyć. Wprowadzona zostanie możliwość użycia napisu przy wyborze odpowiedniego case'a. Np:
String str = "test";
switch(str) {
case "test":
System.out.println("TEST!");
break;
case "test2":
System.out.println("TEST2");
break;

default:
System.out.println("KLOPS!");
break;
}

Przeciążenie operatora dla BigDecimal
Tutaj trochę dyskusji na blogach jest. Czy w ogóle to wprowadzać, czy wprowadzić tylko dla BigDecimal, czy wprowadzić ogólnie przeciążenie operatora.
Wg mnie wprowadzenie przeciążenia operatora narobi sporo zamieszania. Java jest już bardzo rozwiniętym językiem i wprowadzenie takiego mechanizmu może więcej zaszkodzić niż pomóc. Chyba, że nie dotykać biblioteki standardowej, umożliwić dziedziczenie po wszystkich klasach z niej i niech programiści sami sobie radzą. Co oczywiście, też jest beznadziejnym podejściem do sprawy...
nie wypowiadam się;]

Właściwości dla obiektów JavaBeans
Jak w C# lub VisalBasicu, bezpośredni dostęp do właściwości beanów a nie przez gety lub sety:
public property String name;

Blok automatycznego zarządzania zasobami
To jest dobre! I bardzo proszę o wprowadzenie;] Jest propozycja by wprowadzić blok kodu po wykonaniu którego zasoby w nim użyte będą natychmiastowo usuwane. Coś żeby obejść problem bloku finally (tzn. momentu jego wykonania) a zarazem wprowadzenie możliwości usuwania kilku zasobów razem.
do (BufferedInputStream bis = ...; BufferedOutputStream bos = ...) {  
// ...
} // tutaj zmienne bis i bos zostaną usunięte z pamięci

Wywołania łancuchowe
To jest dość ciekawe. Metody zwracające void będą w niektórych przypadkach zwracać this przez co będą możliwe takie wywołania:
class Micky {
public void scream() { // ... }
public void waveHand() { // ... }
public void talk(String text) { // ... }
}

Micky micky = new Micky();
micky.scream().waveHand().talk("Hello, world!");
Ale szczerze to nie sądze aby to wprowadzono ;-)

Ulepszony blok catch
Nareszcie! Oby to wprowadzono ! Pewnie wielu z Was denerwowały tasiemce bloków catch w stylu:
try {
mbs.registerMBean(mbean, name);
} catch (InstanceAlreadyExistsException e) {
System.err.println(e);
} catch (MBeanRegistrationException e) {
System.err.println(e);
} catch (NotCompliantMBeanException e) {
System.err.println(e);
}
Teraz to będzie mogło być zastąpione taką konstrukcją:
try {
mbs.registerMBean(mbean, name);
} catch (InstanceAlreadyExistsException | 
MBeanRegistrationException |
NotCompliantMBeanException e) {
System.err.println(e);
}
Po prostu rozdzielamy typy wyjątków operatorem | i obsługujemy wszystkie w jednakowy sposób.

Domknięcia
To chyba największy bonus językowy. Jak widać coraz więcej jezyków zaczyna obsługiwać takie konstrukcje. Jeśli chodzi o jakieś szczegółowe informacje to niestety nic nie zostało jeszcze postanowione. Społeczność Javy ciągle spiera się w jakiej postaci mają zostać one wprowadzone. Zaciekawionych tematem zachęcam do przeczytania tego artykułu

To by był taki zarys nowości w jakie mogą się pojawić w Java 7. Osoby bardziej zainteresowane tematem zachęcam do poczytania artykułów do których linki pojawiły się w poście ;-)
Rozwojowe wersje JDK 7 można pobrać ze strony https://jdk7.dev.java.net/.
Blog poświęcony Java 7: java7.tumblr.com/

UPDATE
Napisałem kolejną część przygód Javy 7 z nowymi informacjami co udało się przepchnąć do standardu -> Co nowego w Java 7 ? Część druga.

UPDATE 2
I kolejna część: Co nowego w Java 7 ? Część trzecia - będą domknięcia !

UPDATE 3
I ostatnia: (Prawdopodobnie ostatnie) Podsumowanie nowości w Java 7

czwartek, 11 września 2008

wtorek, 9 września 2008

Filtrowanie i sotrowanie danych w RMS

Jakiś czas temu pisałem o RMS w J2ME wspominałem tam, że przeglądając zbiór obiektem typu RecordEnumeration możemy filtrować dane oraz je sortować. Dzisiaj trochę więcej o tym napiszę.
Najpierw przypomnijmy sobie jak pozyskać obiekt RecordEnumerate. Dokonujemy tego poprzez wykonanie metody enumerateRecords na obiekcie reprezentującym zbiór rekordów. Metoda ta posiada 3 parametry (kolejno):
- RecordFilter - filtr
- RecordComparator - obiekt do sortowania rekordów
- boolean - parametr czy uwzględniać zmiany w zbiorze (omawiałem wcześniej).

No to zaczniemy od filtrowania...
RecordFilter - pod tą nazwą kryję się interfejs postaci:
public interface RecordFilter {
boolean matches(byte[] candidate);
}

Klasy implementujące ten interfejs muszą posiadać tylko jedną metodę matches testującą czy dany element może należeć do zbioru wynikowego. Metoda zwraca true gdy element spełnia podane warunki lub false w przeciwnym wypadku. Na tej podstawie stwierdzane jest czy dodać go do zbioru wynikowego czy nie.
Dla przykładu napiszmy klase, która będzie przepuszczać tylko liczby większe od zera:
import javax.microedition.rms.RecordFilter;

/**
*
* @author -WooKasZ-
*/
public class PositiveFilter implements RecordFilter {
public boolean matches(byte[] candidate) {
// zakładamy, że rekordy są 4 bajtowe i zawierają liczbę typu int
return Integer.parseInt(new String(candidate)) > 0; // bleee można to ładniej zrobić ?
}
}


Sortowanie.
RecordComparator to także interfejs o następującej definicji:
public interface RecordComparator {
int compare(byte[] rec1, byte[] rec2);
}

Metoda compare porównuje dwa elementy i stwierdza czy rec1 jest większy, mniejszy lub równy. Oczywiście metoda porównywania musi zostać zaimplementowana przez programistę. Dozwolone są następujące wartości zwracane:
- RecordComparator.EQUIVALENT - wartości równe
- RecordComparator.FOLLOWS - pierwszy parametr jest większy od drugiego
- RecordComparator.PRECEDES -pierwszy parametr jest mniejszy od drugiego

Przykład (sortowanie liczb):
import javax.microedition.rms.RecordComparator;

/**
*
* @author -WooKasZ-
*/
public class SortComparator implements RecordComparator {
public int compare(byte[] rec1, byte[] rec2) {
int first = Integer.parseInt(new String(rec1));
int second = Integer.parseInt(new String(rec2));

if (first == second)
return RecordComparator.EQUIVALENT;

if (first > second)
return RecordComparator.FOLLOWS;

return RecordComparator.PRECEDES;
}
}


To wszystko! Możemy za pomocą tych dwu typów klas wybierać tylko dane które nam są potrzebne i układać je w odpowiedniej kolejności.

niedziela, 7 września 2008

kombinacja UNION i ORDER BY w Firebird

Dziś miałem problem z kombinacją UNION i ORDER BY w bazie danych Firebird.
Zupełnie nie rozumiałem dlaczego występuje błąd i zapytanie postaci (tylko przykład):
SELECT
TABELA1.KOLUMNA
FROM
TABELA1
WHERE
TABELA1.INNA_KOLUMNA > 10
UNION
SELECT
TABELA1.KOLUMNA
FROM
TABELA1
WHERE
TABELA1.INNA_KOLUMNA < 50
ORDER BY TABELA1.KOLUMNA

zwraca mi błąd:
Invalid command invalid ORDER BY clause

Poszperałem po google i okazało się, że w kombinacji UNION z ORDER BY nie można używać nazw kolumn bezpośrednio tylko trzeba podać numer wg której z kolei kolumny wynikowej ma być posortowana tabela.
Czyli poprawne zapytanie ma postać:
SELECT
TABELA1.KOLUMNA
FROM
TABELA1
WHERE
TABELA1.INNA_KOLUMNA > 10
UNION
SELECT
TABELA1.KOLUMNA
FROM
TABELA1
WHERE
TABELA1.INNA_KOLUMNA < 50
ORDER BY 1

Nie wiem dlaczego tak jest, nie wnikałem. Ale warto wiedzieć, gdyż czasem UNION się przydaje ;)

sobota, 9 sierpnia 2008

Firebird i cytaty w PHP


Każdy programista PHP (i nie tylko!) chyba wie, że cytaty wymagają specjalnej kontroli, jej brak może być źródłem ataków typu SQL Injection.
Pamiętałem o tym również i ja i zabezpieczyłem się oczywiście włączając opcję automatycznego dodawania backslashy przy znakach specjalnych - magic_quotes_gpc. Np. wysyłając tekst w formularzu:
\t\e\s\t

Po stronie serwera otrzymam:
\\t\\e\\s\\t

Czyli wszystko fajnie :)

Troszkę się zdziwiłem gdy na mantisie dwa dni temu zobaczyłem zgłoszony błąd od testera, że nie sprawiają mu problemów ataki typu SQL Injection. Do głowy przyszło mi tylko jedna myśl - "WTF!?".
Obadałem kod sprawdzając czy napewno dodawane są backslashe - all ok.
Później uznałem, że trzeba to samemu sprawdzić. Wpisuje w formularzy blabla', wysyłam formularz i boom;] sypneło się:) No tylko dlaczego skoro po stronie serwera otrzymałem: blabla\' ?? Google.pl....
Trochę poszperałem aż trafiłem na artykuł o obsłudze cytatów w Firebird. I tam ciekawostka ! Okazało się, że w Firebirdzie napis: blabla\' oznacza po prostu blabla\' ! :) Żeby zabezpieczyć taki ciąg nie należy dodawać backslasha tylko wpisać blabla'' ! Czyli podwajamy znak specjalny (zachciało im się innowacji:|). Co więcej php ma funkcje do automatycznego wykonywania tego (pod tym względem <3 PHP - ma ogrom przydatnych funkcji) ! :D Wystarczy ustawić zmienną magic_quotes_sybase na On w php.ini i jest ok:)
Jeśli nie ma się dostępu do php.ini trzeba to wykonać przez .htaccess ponieważ ustawienie tego przez ini_set z tego co zauważyłem nie jest możliwe.

Treść .htaccess:
php_value magic_quotes_sybase On


No i problem rozwiązany :)

piątek, 8 sierpnia 2008

Hype - Lies and Speeches

Sponsorem dzisiejszego wieczoru jest zespoł Hype z albumem Lies and Speeches :)
Polecam!
  


Piosenka Anybody here najbardziej wpadła mi w ucho:)

I ogólnie polecam serwis Jamendo.com ! Dużo dobrej muzyki za darmo !!

niedziela, 3 sierpnia 2008

Filip Kubiatowicz mistrzem świata !!

Chciałbym serdecznie pogratulować mojemu koledze Filipowi (aka Nosferatu) za zdobycie tytułu Mistrza Świata w katerogi semi-pro w futbolu stołowym znanym także jako "piłkarzyki" lub "trambambula" (o_O).


Życzę Ci samych takich sukcesów Nosfe !!
Więcej informacji na Wiadomości24.pl

ps. jeszcze trochę i może uda Ci się ze mną wygrać ^^
pps. ale dziś tu nowych postów :P

PHP 5.3 alpha1 dostępna


Czekałem czekałem i się... nie doczekałem :P Miała się pojawić do końca czerwca, pojawiła się pod koniec lipca i to jeszcze alfa :P No ale jest - kamień milowy w rozmowu PHP nareszcie dostępny do testów;]
Pisałem już wcześniej czego możemy się spodziewać w wersji 5.3. Do tej listy doszło jeszcze kilka rzeczy ! :)
- LAMBDA (!!)
- domknięcia
- nowy typ pliku - 'phar' czyli php archive, który może przechowywać w sobie całą aplikację gotową do wdrożenia
- opcjonalny odśmiecacz pamięci
- NOWDOC (tego za bardzo jeszcze nie czaje :P Jak obadam to napisze więcej o co chodzi:P)

warto było czekać :) Co prawda nadal nie mam zainstalowanej tej wersji gdyż wersja pod windowsa jeszcze się nie pojawiła (ma być w ciągu kilku dni), ale jak się pojawi i zapoznam bardziej szczegółowo to coś tu skrobnę ;)

Plik do pobrania czeka : tutaj

RMS w J2ME

Wracamy do tematu J2ME :) Inżynierka będzie m.in. dotyczyła tego wynalazku więc trzeba zgłębiać tajemną wiedzę zanim będzie za późno :P
Dziś trochę o zapisie danych w MIDletach. Telefony komórkowe są urządzeniami typu "co kraj to obyczaj" czyli (w tym przypadku) sposób zapisu danych może być różny na różnych modelach u różnych producentów. Jednak dla J2ME został opracowany uniwersalny sposób dla wszystkich urządzeń o nazwie RMS - Record Management System.

Dane zapisuje się w rekordach, które zawierają się w zbiorach. Rekord jest przez programistę widziany jako tablica bajtów, więc trzeba się samemu troszczyć o to co zawierany dany rekord. Każdy zbiór posiada swojego właściciela (MIDlet) i może być on współdzielony przez wiele MIDletów. Zbiór posiada unikalny identyfikator - nazwe, natomiast rekord w zbiorze posiada unikalny numer.
Nie ma ograniczeń co do liczby zbiorów jakie może utworzyć MIDlet, jedynym ograniczeniem jest dostępna pamięć.

Tworzenie zbioru
Nad zbiorami rekordów w J2ME czuwa klasa RecordStore.
Aby utworzyć jakiś zbiór należy wywołać jej statyczną metodę: openRecordStore(String recordStoreName, boolean createIfNecessary) której parametry kolejną oznaczają nazwę zbioru oraz flagę czy zbiór ma zostac utworzony jeśli nie istnieje.
W MIDP 2.0 dodano dwie nowe metody openRecordStore o innych parametrach i bardziej specjalistycznych zadaniach. M.in. z ustawieniem uprawnień i przypisywaniem danego zbioru do konkretnego MIDletu.

Metoda zwraca nam utworzony (lub otworzony) zbiór na którym możemy wykonywać operacje zapisu i odczytu. Zanim do tego przejdziemy dodam jeszcze, że możemy się spodziewać wystąpienia następujących wyjątków:

RecordStoreNotFoundException - zbiór nie istnieje (w przypadku gdy nie ma być automatycznie utworzony)
RecordStoreFullException - brak dostępnej pamięci
IllegalArgumentException - błędna nazwa zbioru
RecordStoreException - inny błąd

na koniec jeszcze przykład tworzenia nowego zbioru:
RecordStore store = RecordStore.openRecordStore("test", true);

// zrzuci wyjątek jeśli zbiór nie istnieje
RecordStore secondStore = RecordStore.openRecordStore("test2", false);

Zapis w RMS
Na pierwszy ogień weźmiemy zapis danych. Mamy do dyspozycji dwie metody klasy RecordStore:
- int addRecord(byte[] data, int offset, int numBytes)
dodaje nowy rekord do zbioru i zwraca nam ID rekordu. Jako parametry musimy podać kolejne: dane do zapisu, od którego bajtu ma być zapisywane oraz ile bajtów ma zostać zapisanych.
- void setRecord(int recordId, byte[] newData, int offset, int numBytes)
ta metoda służy do zastąpienia rekordu nowym. Dodatkowym parametrem jaki trzeb podać jest ID rekordu który ma być zastąpiony, reszta jak powyżej.

Ponieważ zapisujemy tablice bajtów najlepiej posłużyć się strumieniami. Idealnie nadaje się do tego strumień ByteArrayOutputStream.
Może teraz jakiś przykład:
RecordStore bd = RecordStore.openRecordStore("test", true);

ByteArrayOutputStream arrayStream = new ByteArrayOutputStream();
// do zapisu danych różnych typów
DataOutputStream out = new DataOutputStream(arrayStream);
// wpisujemy do strumienia tekst
out.writeUTF("testujemy zapis!");
// pobieramy tablice bajtów
byte[] data = arrayStream.toByteArray();
// zapisujemy do rekordu
bd.addRecord(data, 0, data.length);

// zamykamy strumień i zbiór
out.close();
bd.closeRecordStore();

Ważne jest aby zamykać strumień i zbiór, urządzenia mobilne nie posiadają dużo pamięci więc należy je oszczędzać.
Dodam jeszcze, że podczas każdej operacji addRecord, setRecord i deleteRecord na zbiorze inkrementowana jest jego wersja. Wersję zbioru można otrzymać poprzez wywołanie int getVersion().

Odczyt w RMS
Jeśli nie znamy zbiorów MIDletu możemy pobrać ich nazwy za pomocą metody statycznej RecordStore.listRecordStores(). Zwraca ona tablicę Stringów lub null w przypadku gdy nie ma żadnego dostępnego zbioru.
Gdy dobierzemy się do konkretnego zbioru i go otworzymy możemy zacząć przeglądać rekordy w nim zawarte.
W tym celu użyjemy klasy RecordEnumeration. Pobranie obiektu tego typu następuję przez wywołanie metody
enumerateRecords(RecordFilter filter, RecordComparator comparator, boolean keepUpdated). Parametry tej metody oznaczają:
- filter - obiekt służący do filtrowania rekordów (o tym innym razem)
- comparator - obiekt służący to porównywania rekordów i ułożenia ich w odpowniednim porządku (o tym innym razem)
- keepUpdate - jeśli prawda to będą brane pod uwagę zmiany w rekordach podczas ich przeglądania. Ta opcja jest dość ważna i może wpłynąć na wydajność aplikacji.

Do samego przeglądania przydadzą nam się jej dwie metody:
- bool hasNextElement() sprawdza czy istnieją jeszcze jakieś elementy
oraz
- byte[] nextRecord() - zwraca kolejny element
Przykład:
RecordStore bd = RecordStore.openRecordStore("test", false);

RecordEnumeration recEnum = bd.enumerateRecords(null, null, false);
while (recEnum.hasNextElement()) {
byte[] data = recEnum.nextRecord();
// jakieś działania
}

bd.closeRecordStore();

Można oczywiście użyć ByteArrayInputStream wraz z DataInputStream do przeglądania konkretnego rekordu:
DataInputStream in = new DataInputStream(
new ByteArrayInputStream(recEnum.nextRecord()));
String text = in.readUTF();

Usuwanie rekordów/zbiorów
Na koniec usuwanie. Mamy do dyspozycji dwie proste metody:
- void deleteRecord(int recordID) - usuwa rekord o podanym ID ze zbioru
- static void deleteRecordStore(String recordStoreName) - usuwa cały zbiór rekordów o podanej nazwie. Uwaga - zbiór musi być zamknięty inaczej otrzymamy wyjątek RecordStoreException.

No to to by było na tyle z podstaw korzystania z RMS. Mam nadzieje, że przedstawiłem to dość klarownie. Nie rozglądałem się ale mam nadzieje, że istnieje jakaś gotowa biblioteka, która zapewniała by kontrole typów które są przechowywane w tych rekordach, bo teraz to trochę "niskopoziomowo" się to obsługuje ;P Zachęcam także to przejrzenia API RMS. Znajduje się tam jeszcze sporo metod o których nie wspomniałem a zapewniają bardziej zaawansowane możliwości.

wtorek, 29 lipca 2008

Google XML Pages

Google udostępniło system szablonów na bazie którego od wielu lat działają takie serwisy jak Blogger, Google Analytics czy Google Reader. Przeznaczony jest do wyświetlania stron XML/SGML. Na tę chwilę dostępny jest dla języka Java i w przygotowaniu C++ (chociaż na jednej stronie znalazłem, że podobno już jest gotowy - kodu nie znalazłem niestety).
Aktualna wersja to 0.2 beta, dostępna jest na stronie Google Code : GXP.
Możliwości jakie posiada GXP można obejrzeć na prezentacji: GXP Introduction Slides.

Jednak zanim przyjdzie nam z tego korzystać trzeba będzie poczekać na dokumentację której jak narazie nie ukończono ;P

poniedziałek, 28 lipca 2008

My life for Auir !


wtorek, 22 lipca 2008

Wymiana oleju to strata pieniędzy ?


Znalazłem gdzieś w sieci artykuł w którym postawiono tezę, że okresowa wymiana oleju w samochodzie to strata pieniędzy, która dodatkowo szkodzi! Najciekawsze jest to, że taką tezę postawił były dyrektor Castrol - Henk de Groot.
Zapraszam do lektury.
ARTYKUŁ


niedziela, 20 lipca 2008

troszkę inny 'switch'

Całkiem niedawno odkryłem ciekawe, inne użycie switcha (pewnie wszyscy je znali a ja ciągle siedziałem w średniowieczu ale co tam). W każdym skrypcie zawsze znajdą się linie kodu podobne do tego:
$i = 1;

if ( $i == 0 ) {
echo 'Goodnight, world!!';
} elseif ( $i == 1 ) {
echo 'Hello, world!';
} elseif ( $i > 4 ) {
echo 'Dont cry for me.... ARGENTINA !!';
} else {
echo 'die die die!';
}
(warunek prosty dla przykładu)
Mnie osobiście takie tasiemce elseif elseif elseif troszkę brzydzą i dla mnie taki kod jest nieczytelny (zwłaszcza gdy warunki robią się duże). Taki kod można prosto przerobić w konstrukcję switch, która będzie "ładniejsza" w taki sposób:

$i = 1;

switch ( true ) {
case ( $i == 0 ):
echo 'Goodnight, world!!';
break;

case ( $i == 1 ):
echo 'Hello, world!';
break;

case ( $i > 4 ) :
echo 'Dont cry for me.... ARGENTINA !!';
break;

default:
echo 'die die die!';
break;
}
Od razu ładniej:) Zachowanie mamy praktycznie takie same. Kodu może troszkę więcej powstaje ale co tam! Ważne, że ładnie :)
Co do szybkości wykonywanie to nie sprawdzałem, mam to gdzieś :)
Dodam jeszcze, że należy pamiętać, że zawsze zostanie wykonany tylko pierwszy 'case' który ma spełniony warunek a następne nie będą już sprawdzane (nawet gdy ich warunek spełniony). Oczywiście pomijam tutaj możliwość opuszczenia 'break'.

Wiem, że nic genialnego nie odkryłem ale może komuś się przyda/spodoba ^^

niedziela, 29 czerwca 2008

Elvis Costello & The Imposters


Wczoraj wybrałem się na koncert organizowany z okazji Festiwalu Malta na koncert finałowy Elvisa Costello & The Imposters. Koncert odbył się przy jeziorze Malta na specjalnie zbudowanej scenie. Pogoda zniechęcała do przybycia - dość ostro padało. Gdy przybyłem na miejsce to było tam może z 30 osób. No ale gdy rozpoczął się koncert rozpogodziło się i gdy się odwróciłem (stałem pod samą sceną) zobaczyłem SPORO więcej osób - miło:)
Jeśli chodzi o sam koncert to na początku wiało nudą :P ale z czasem coraz bardziej się rozkręcało, żeby na bis dać już ostro :) Ogólnie dobrze się bawiłem. Poniżej zamieszczam kilka fotek zrobionych moim marnym aparatem w telefonie.

Elvis Costello - koncert - Malta 28.06.08

Tę piosenkę chyba każdy będzie kojarzyć Elvis Costello - She z filmu Notting Hill


Koncert można obejrzeć dziś (29 czerwca 2008) o godzinie 22:15 na TVP2.

Linki:
Elvis Costello na wiki
Elvis Costello - The Official Website

poniedziałek, 23 czerwca 2008

Rewolucje w Matrixie!

Tego o prostu nie mogłem tutaj nie umieścić! Najlepsza recenzja Matrixa jaką czytałem:

Ok, koniec głupot (ironia), wracam do Aplikacji Internetowych wg J.C...

sobota, 21 czerwca 2008

Przerwa techniczna !


Niestety z powodu egzaminów i innych zaliczeń na uczelni nie mam za bardzo czasu tutaj nic pisać. Przede mną jeszcze jeden egzamin (aplikacje internetowe) i zaliczenie (optymalizacja kombinatoryczna). Jak na razie napisałem dwa egzaminy i powinny być do przodu ;-) No ale pewności nie mam.

W każdym razie ponownie w ramach relaksu coś wrzucę :) Tym razem Kabaret Ani Mru Mru w programie "Mój pierwszy raz" Jerzego Kryszaka! Miłego ;)


niedziela, 15 czerwca 2008

Fun Factory - Doh Wah Diddy

W ramach relaksu podczas nauki na egzamin... :) Słuchałem tej piosenki jak byłem bardzo mały na kaseciaku ;D HIT!


czwartek, 12 czerwca 2008

Eclipse DemoCamp w Poznaniu


24 czerwca o godzinie 18:00 odbędzie się spotkanie sympatyków środowiska Eclipse - Eclipse DemoCamp. Miejscem spotkania jest Pub Piwnica 21 znajdująca się na ulicy Wielkiej. Kto nie wie jak tam trafić to poniżej ma mapkę (zaszalałem!:D):

Wyświetl większą mapę

Aby móc się tam dostać trzeba się dopisać do listy na tej stronie: LINK. Znajdują się tam też bardziej szczegółowe informacje co się będzie działo i kto o czym będzie mówić. Mam zamiar także się tam zjawić:)
Serdecznie zapraszam!