2008-12-18

Uaktualnienie Eclipse do wersji 3.4.1

Zaktualizowałem Mac OSowe Eclipse do wersji 3.4.1 (menu Help / Software Updates...). Wszystko poszło gładko, ale po restarcie środowiska zobaczyłem komunikat:

The Eclipse executable launcher was unable to locate its companion shared library.

i Eclipse kompletnie odmówił współpracy. Więcej informacji można uzyskać uruchamiając go z terminala:

dlopen(../../../plugins/org.eclipse.equinox.launcher.carbon.macosx_1.0.100.v20080509-1800, 2): image not found

Rzeczywiście takiego pliku ani katalogu nie ma, ale jest katalog o bardzo podobnej nazwie:

org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731

Pozostała kwestia gdzie owa ścieżka jest zaszyta. Ponieważ Eclipse odmawia posłuszeństwa zaraz po starcie, to pierwszym kandydatem jest plik eclipse.ini. I rzeczywiście, po wpisaniu nazwy istniejącego katalogu jest ok.

2008-10-04

HP DeskJet F4180 i AirPort Extreme

O jakości sterowników HP mam jak najgorsze zdanie, więc szczególnie się nie zdziwiłem gdy moja drukarka po podłączeniu do routera przestała drukować w kolorze (przez USB działała dobrze). Zainstalowanie wszelkich aktualizacji dostępnych na stronach HP i Apple nic zmieniło, wysłałem więc zgłoszenie do pomocy technicznej HP. Okazuje się, że jest ona równie wysokiej jakości jak sterowniki - minął prawie miesiąc, a żadnej odpowiedzi nie dostałem. Pozostało znalezienie rozwiązania samemu. Na iBooku z Tigerem używałem sterowników gimp-print (teraz noszących nazwę gutenprint), więc najpierw zerknąłem na listę obsługiwanych przez nie drukarek. Niestety nie było na niej HP DeskJet F4180. Po sprawdzeniu kilku mniej lub bardziej trafnych wyników googlania znalazłem stronę projektu OpenPrinting. Dostępne są tam sterowniki dla ogromnej liczby drukarek, w tym - w pakiecie hpijs - dla F4180 (hura!). Do działania wymagają one filtrów Foomatic, które z kolei używają Ghostscripta. Istotna jest kolejność instalacji: najpierw Foomatic i Ghostscript, dopiero potem hpijs (w przeciwnym razie instalator hpijs zapętli się). Na koniec trzeba zmienić sterownik w preferencjach systemowych. Co ciekawe, to wersja Foomatic/hpijs jest oznaczona jako "recommended" a nie standardowy sterownik HP. Komplet pakietów instalacyjnych można znaleźć tutaj. Najlepiej wybrać najnowsze dostępne wersje, ja użyłem:
  • hpijs 2.7.10
  • Foomatic 2008-01-30
  • Ghostscript 8.6.1

2008-10-02

A teraz coś z zupełnie innej beczki

Podczas okresowego porządkowania zdjęć trafiłem na kilka takich, które nadal mi się podobają. To ewenement, bo generalnie jestem krytyczny wobec swoich dzieł (za co świat powinien być mi wdzięczny), szczególnie oglądając je po dłuższym czasie od wykonania. Na początek dwa, za jakiś czas jeszcze kilka wyszukam.


zima zima zimaBardzo, bardzo dawne czasy, kiedy w Polsce jeszcze bywały zimy.


deszczOdbicie lampy sodowej w kałuży.

[aktualizacja 2009.03.15]

Przez bliżej nieokreślony czas zdjęcia nie były widoczne - coś popsułem na koncie flickrowym. Przepraszam wszystkich fanów mojej twórczości za utrudnienia.

2008-09-27

iPhone

Na początku września skończyła się moja umowa z Erą i musiałem wybrać nowy telefon na kolejne dwa lata. Pod uwagę brałem Nokię N95 8GB, Era MDA IV (czyli HTC Diamond) i iPhone'a. Całkiem możliwe, że zdecydowałbym się na N95 - wszystkie moje poprzednie telefony to były Nokie - ale cena była mocna zaporowa. Przy obiektywnym porównaniu specyfikacji Diamonda i iPhone ten pierwszy wypada lepiej, ceny w Erze mają porównywalne, z kolei za iPhonem przemawia o niebo lepszy interfejs użytkownika. Gdybym nie miał już ASUSa z GPSem to wybrałbym Diamonda (nawigacja w iPhone ze względu na brak map to tylko ciekawostka). I chyba prędzej czy później żałował bym tej decyzji.

OS X dla iPhone jest naprawdę wygodny, funkcjonalny i przede wszystkim spójny - zarówno w aplikacjach systemowych jak i instalowanych z App Store. Wiem, że Diamond (i zaprezentowany niedawno Samsung Omnia) mają swoje nakładki usprawniające i upiększające Windows Mobile, ale ciągle to tylko nakładki - zastępują ekran Today, podmieniają programy systemowe (np. odtwarzacz multimediów), jednak większość aplikacji wykorzystuje nadal standardowe GUI.

Trochę brakuje możliwości wysyłania MMSów. Niby można zamiast nich pisać maile, ale to nie to samo - adresat MMSa przeczyta (i zobaczy) go zazwyczaj od razu, maile sprawdza się dużo rzadziej. Drugi minus to brak możliwości uruchamiania w tle aplikacji firm trzecich. O ile systemowy Kalendarz wyświetla powiadomienia o nadchodzących terminach, to już aplikacja Todo kupiona w App Store nie. Pomimo tego, po dwóch tygodniach używania nie widzę sensownej alternatywy dla iPhone'a (chyba, że ktoś uruchomi OS X na Omnii).

Kilka programów, których używam na co dzień:

[aktualizacja 2008.10.02]

Najnowszy nabytek:
  • Track'n Trail - aplikacja zapisująca (w oparciu o GPS) przebytą trasę i umożliwiająca jej eksport do Google Earth

[aktualizacja 2008.10.06]

W serwisie fkn.pl opublikowane zostało porównanie iPhone'a i Omnii.

2008-08-24

Wehikuł Czasu i panikujący kelner

Po raz pierwszy odkąd mam Maka zawiesił mi się system. Jabłkowy odpowiednik blue screen of death jest szary i w kilku językach sugeruje wciśnięcie i przytrzymanie przycisku zasilania, co też niezwłocznie uczyniłem. Mac OS wstał bez problemu, a następnie zasugerował poinformowanie o błędzie Apple'a. Przed wysłaniem raportu zerknąłem na zakładkę Problem Details i okazało się, że panika miała miejsce w kodzie obsługującym system plików:

panic(cpu 0 caller 0x00321C20): "hfs_UNswap_BTNode: invalid forward link (0xC647002C)\n"@/SourceCache/xnu/xnu-1228.5.20/bsd/hfs/hfs_endian.c:254

W momencie padu Time Machine właśnie zaczynał tworzenie backupu, więc uznałem że chodzi o zewnętrzny dysk podpięty do AirPorta. Aby zyskać pewność wybrałem z menu Back Up Now i rzeczywiście po kilkunastu sekundach system znowu się wywrócił. Nie pozostało nic innego jak wyłączyć Time Machine, odpiąć dysk od routera i podłączyć bezpośrednio do Maka aby można go było sprawdzić przy pomocy Disk Utility. Po kliknięciu przycisku Repair Disk rzeczywiście został znaleziony i naprawiony jakiś błąd, jednak po podłączeniu dysku z powrotem do AirPorta i rozpoczęciu backupu kernel znowu spanikował... Tym razem Disk Utility nic nie znalazł, więc konieczne okazało się sprawdzenie obrazu dysku (sparse disk image) stanowiącym backup. Tu już nie było tak prosto jak z partycją - Disk Utility nie potrafi go zamontować. Po chwili googlania znalazłem informację o narzędziu hdiutil, które umożliwia dołączenie obrazu dysku jako urządzenia. A konkretnie:

sudo hdiutil attach -nomount -readwrite /Volumes/Backup/nazwa_obrazu_dysku.sparsebundle

... wyświetla listę urządzeń odpowiadających obrazowi z backupem, na przykład:

/dev/disk1 Apple_partition_scheme
/dev/disk1s1 Apple_partition_map
/dev/disk1s2 Apple_HFSX

Interesuje nas trzecie z tych urządzeń, wpisujemy więc w terminalu:

sudo fsck_hfs -f /dev/disk1s2

i po dość długim czasie obraz dysku zostanie naprawiony. Albo i nie, ponieważ polecenie fsck_hfs nie zawsze jest w stanie poprawić wszystkie błędy w jednym przebiegu. U mnie trzeba było uruchomić je dwukrotnie aby w końcu wyświetlony został komunikat

** The volume ... was repaired successfully.

Cały czas nie wiem co było przyczyną uszkodzenia backupu, na szczęście jak dotąd problemy się nie powtórzyły.

2008-07-04

OSGi, Spring Dynamic Modules, Eclipse i Maven - część 2.

Druga część tekstu o Spring Dynamic Modules opublikowana na wordpress.com.

2008-06-28

Zmiana czcionki w interfejsie Gmail

Jestem przyzwyczajony do pisania maili czcionką nieproporcjonalną (czy jak kto woli czcionką o stałej szerokości), niestety webowy interfejs Gmail nie ma takiej opcji w ustawieniach. Po wpisaniu w wyszukiwarce frazy "gmail fixed width font" znalazło się sporo stron z opisami jak taką czcionkę ustawić. Pomimo, że żaden z nich nie zadziałał u mnie od ręki, to ogólna idea była słuszna: trzeba korzystać z Firefoxa (ale to przecież oczywiste) i wpisać stosowny styl do pliku chrome/userContent.css. Lokalizacja tego pliku zależy od systemu operacyjnego, tutaj można się dowiedzieć gdzie go szukać. Do sprawdzenia jaki styl należy zmodyfikować użyłem Firebuga i ostatecznie mój plik userContent.css wygląda tak:
@-moz-document domain(mail.google.com) {
textarea.iE5Yyc {
font-family: monospace !important;
font-size: 12px !important;
}
body.tr-field {
font-family: monospace !important;
font-size: 12px !important;
}
}
Oznaczenie !important nie należy do standardu CSS, ale jest rozpoznawane przez Firefoxa. Oznacza, że dany wpis z userContent.css ma nadpisać styl pobrany z serwera.

2008-06-06

OSGi, Spring Dynamic Modules, Eclipse i Maven - część 1.

[aktualizacja 2008.06.20]

Edycja w Bloggerze wpisu zawierającego XML i kod źródłowy (wcięcia!) to nieporozumienie... Dlatego teksty dotyczące programowania będą lądować w praktycznej baryłeczce znajdującej się na wordpress.com.

2008-05-05

Ewolucja

W czasach mojej młodości (czyli dawno temu) jednym z bardziej pożądanych elementów w klockach Lego był komputer. Komputery i monitory trafiały się tylko w niektórych zestawach kosmicznych, w każdym razie wszystkie które ja miałem pochodziły właśnie z nich. Były to terminale tekstowe, z zielonym ekranem - wszystko zgodne z ówczesnymi realiami.

Dwadzieścia lat później komputery stały się powszechne - są w remizie strażackiej, na łodzi policyjnej, nawet w samobieżnym dźwigu. Pomimo że zewnętrzna forma się nie zmieniła, to widoczny jest już okienkowy system operacyjny.

Najnowszy model (z drugiej wersji remizy, rocznik 2007) ma ekran LCD i klawiaturę. Ponieważ monitor i klawiatura są jedynymi elementami składowmi, to pewnie jakiś iMac.
Swoją drogą w żadnym zestawie nie widziałem jeszcze telefonu komórkowego.

2008-04-19

Zmiana rozmiaru partycji HFS

Przy okazji przenosin ze starego laptopa na nowego dorosłem do robienia backupów. W podjęciu tej doniosłej decyzji na pewno pomógł Wehikuł Czasu dostępny w Leopardzie - wcześniej po prostu nie chciało mi się szukać, konfigurować i testować programów robiących kopie zapasowe. Kupiłem zewnętrzny dysk My Book Essential Edition, sformatowałem go jako HFS, kilkoma kliknięciami skonfigurowałem co i gdzie ma być zapisywane i po dwóch minutach Mac zaczął tworzenie pierwszej kopii. Trochę to trwało - na dysku w ciągu niecałego miesiąca zebrało się 40 GB w około milionie (!) plików - ale kolejne przyrostowe backupy były już szybkie.

Po kilku dniach uznałem (rychło w czas), że dobrze byłoby zrobić dodatkową partycję dla VirtualBoxa. W Leopardzie można za pomocą Disk Utility przeskalowywać partycje "w locie", nawet bez odmontowywania jej, ale u mnie ta możliwość była niedostępna. Okazało się, że winny jest typ tablicy partycji: dysk zewnętrzny miał MBR, a zmiana rozmiaru jest możliwa tylko na dysku z tablicą GUID. Nie znalazłem niestety żadnego narzędzia do konwersji tablicy partycji, więc pozostało tylko ponowne zainicjowanie dysku - na szczęście nie było na nim nic poza backupami z kilku dni. Po utworzeniu partycji od nowa z zaznaczoną opcją GUID rzeczywiście można zmieniać rozmiar, dodawać i usuwać partycje bez żadnego problemu.

A więc, drogie dzieci, czego się dzisiaj nauczyłyście? Dodając nowy dysk, który ma być obsługiwany przez Mac OS X, pamiętajcie o sprawdzeniu typu tablicy partycji.

Przy okazji: partycje GUID są obsługiwane przez Windows Vista, Windows Server 2003 i 2008 oraz 64-bitowy Windows XP.

2008-03-27

MacBook Pro i Cortland

Od około dwóch tygodni mam MacBooka Pro. Laptop jest bliski ideału: szybki, cichy, bardzo dobrej jakości ekran, miłe drobiazgi jak wbudowana kamera czy pilot na podczerwień i oczywiście Mac OS X. Jedyne czego bym jeszcze chciał, to nieco dłuższa praca na baterii - teraz wytrzymuje około 3.5-4 godziny.

Nie obyło się jednak bez zgrzytów: pierwszy egzemplarz który kupiłem miał plamkę przy prawej krawędzi wyświetlacza. Niewielką (jakieś 2-3 piksele), ale widoczną na jasnym tle - najprawdopodobniej uszkodzenie powłoki antyodblaskowej. Tutaj wielkie brawa dla Cortlandu - po trzech dniach od zgłoszenia dostałem nowego laptopa z idealnym ekranem. Dodatkowo drugi MacBook miał już w komplecie Leoparda (pierwszy tylko Tigera). Po pewnym czasie korzystania z nowego sprzętu zauważyłem, że zasilacz wydaje podejrzane dźwięki - dość głośne buczenie i trzeszczenie. Napisałem maila do Cortlandu (tak, jestem uciążliwym klientem) i bez jakichkolwiek problemów dostałem nowy zasilacz. Sprawia lepsze wrażenie, ale jednak nie jest tak bezgłośny jak iBookowy. Może po prostu ten-typ-tak-ma.

Podsumowując: wygląda na to, że jakość Apple to już nie to samo co 3 lata temu, kiedy kupowałem iBooka. Szkoda. Jednocześnie obsługa w Cortlandzie jest naprawdę świetna i mam nadzieję że w razie ewentualnych problemów (odpukać) będzie dalej tak samo.

2008-03-19

Komponent Spring jako ServletFilter

Nic odkrywczego, ale filtrów nie ma w przykładach zawartych w dystrybucji Spring i nie ma o nich słowa w Reference Documentation. Pamiętam że jakiś czas temu popełniłem takowy, ale parę dni temu chcąc znowu użyć tej samej konstrukcji nie pamiętałem szczegółów. Starzeję się. Dlatego, celem utrwalenia zdobytej (ponownie) wiedzy, powstał ten wpis.

Aby możliwe było użycie komponentu Spring jako filtru musi on implementować interfejs javax.servlet.Filter i to wszystko. Potem dopisujemy go w konfiguracji XMLowej lub adnotujemy jak każdy inny bean. Cała sztuczka jest w pliku web.xml aplikacji:

<filter>
<filter-name>nazwa</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Klasa DelegatingFilterProxy będzie delegować wywołania metody doFilter(...) do beana o takiej samej nazwie jak nazwa filtra. Jeżeli chcemy, aby filtr miał inną nazwę, to trzeba dodać parametr targetBeanName:

<filter>
<filter-name>nazwaFiltra</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>nazwaBeana</param-value>
</init-param>
</filter>

Należy pamiętać, że pomimo tego iż bean implementuje interfejs Filter, to jego metody init(...) i destroy(...) domyślnie nie są wywoływane. Aby to zmienić musimy ustawić w konfiguracji kontekstu Spring atrybut targetFilterLifecycle na true:

<bean id="nazwaBeana"
class="klasaBeana"
p:targetFilterLifecycle="true">
...
</bean>

2008-03-14

Wydajność ASUSa A696

Czytając recenzję ETENa Glofiisha X800 na stronie PDAclub.pl trafiłem na ciekawy test wydajności grafiki i procesora PDA. Wykorzystany do tego celu został odtwarzacz The Core Pocket Media Player i "standardowy" trailer Matrixa. W zamieszczonej tam tabelce nie ma ASUSa A696, więc nie pozostało nic innego jak przeprowadzić test samemu.

TCPMP ma kilka sterowników wideo i wyniki różnią się dość znacznie w zależności od wybranej wersji. W przypadku A696 najlepiej wypada Intel XScale, pozostałe dwa (DirectDraw i GDI) są około 20% wolniejsze. Dodatkowo na wynik testu wpływa to, czy PDA ma podłączony zasilacz czy nie - jak można się domyślić zasilany z baterii procesor nie działa z pełną mocą (jednak różnica w teście jest niewielka, około 5%). Testy przeprowadziłem na wersji 0.71 odtwarzacza, z podłączonym zasilaczem i z kartą pamięci SanDisk Extreme III 2GB. Każdy test był powtórzony 3 razy, w tabeli poniżej jest średnia uzyskanych wyników:

 z pamięci wewnętrznejz karty SD
Intel XScale334%316%
DirectDraw259%249%
GDI271%259%

Porównując powyższe wartości z tymi na PDAclub.pl widać, że A696 plasuje się wśród najlepszych PDA z procesorem Intel PXA270 416MHz - jedynie Palmax GPS ma lepszy wynik.

2008-03-09

CXF nie działa ze Spring 2.5.2

A konkretnie CXF 2.0.4-incubator nie działa ze Spring Framework 2.5.2 (w wersjach wcześniejszych jest w porządku). Powodem jest zmiana sposobu konfiguracji kontekstu Spring. Dotychczas w konstruktorze
ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
parametr configLocations mógł mieć wartość null - był w takiej sytuacji zastępowany pustą tablicą. W wersji 2.5.2 nie jest już zastępowany, a w metodzie setConfigLocations (wykorzystywanej przez powyższy konstruktor) następuje próba odczytania rozmiaru tablicy i rzucany jest wyjątek NullPointerException. Błąd został zgłoszony kilka dni temu (numer SPR-4531) i jak na razie nie ma reakcji ze strony autorów - pozostaje cofnięcie się do wersji 2.5.1.

[aktualizacja 2008.03.10]


Nieoceniony Juergen Hoeller zainteresował się tym bugiem - w dzisiejszym night buildzie wersji 2.5.3 ma być poprawiony. Rewelacja po raz drugi (pierwsza była tutaj).

[aktualizacja 2008.03.12]


Nie miałem czasu aby sprawdzić od razu, dopiero dzisiaj ściągnąłem najnowszy build. Oczywiście błąd jest poprawiony.

2008-03-02

Firefox 3

Zmieniłem na domowych komputerach domyślną przeglądarkę na Firefoxa 3 beta 3. Zarówno na Mac OS X jak i na Windows działa bez najmniejszych problemów. Co prawda nie wszystkie rozszerzenia zostały uaktualnione, ale najważniejsze dla mnie - Firebug - w wersji 1.1 beta działa z Firefoxem 3.

Głównym powodem migracji były testy szybkości, z których wynika że wersja 3 beta 3 jest około 2 razy szybsza od 2.0.0.12. Na Windows tego nie widzę, zapewne dlatego że komputer jest względnie szybki (Athlon 2500+), ale na dość leciwym iBooku (PowerPC G4 1 GHz) wzrost prędkości jest odczuwalny. Poza tym nowy Firefox przechodzi bezbłędnie test ACID2 i ma bardzo ładny domyślny temat na Mac OS X - wygląda na to, że na dobre pożegnam się z Safari.

2008-02-18

Spring, CXF i Eclipse

Popełniłem pierwszy w życiu web service. Jak można przeczytać w tytule są to komponenty Springowe udostępniane jako usługi sieciowe za pomocą CXF. Projekt stworzony w Eclipse kompiluje się i działa bez problemu, ale Eclipse'owemu edytorowi XMLa nie podoba się definicja kontekstu Spring:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd"%gt;

<jaxws:endpoint id="webServiceEndpoint"
address="/test"
implementorClass="moja.klasa.WebService">

... implementacja usługi ...
</jaxws:endpoint>

</beans>
W zaznaczonym miejscu sygnalizowany jest błąd:
The matching wildcard is strict, but no declaration can be found for element 'jaxws:endpoint'.
Skoro Eclipse nie może znaleźć deklaracji, to trzeba mu powiedzieć gdzie jej szukać. Z menu wybieramy Window / Preferences, potem Web and XML / XML Catalog, zaznaczmy User Specified Entries, klikamy przycisk Add... i wpisujemy następujące wartości:

Location: jar:file:/lokalna/ścieżka/modules/cxf-rt-frontend-jaxws-<wersja>.jar!/schemas/jaxws.xsd
Key Type: Schema Location
Key: http://cxf.apache.org/schemas/jaxws.xsd

Wybranie wartości Schema Location w polu Key Type jest możliwe dopiero po wpisaniu poprawnej wartości w pole Location.

Po wykonaniu tej operacji dotychczasowy błąd zniknie, ale pojawi się nowy:
Referenced file contains errors (jar:file:/ścieżka/do/bibliotek/cxf-<wersja>.jar).
Problemem jest teraz brak definicji, która jest importowana przez jaxws.xsd. W taki sam sposób jak poprzednio dodajemy drugi wpis:

Location: jar:file:/lokalna/ścieżka/modules/cxf-common-utilities-<wersja>.jar!/schemas/configuration/cxf-beans.xsd
Key Type: Schema Location
Key: http://cxf.apache.org/schemas/configuration/cxf-beans.xsd

i tym razem jest to już wystarczające.

Opisany sposób jest oczywiście uniwersalny - można tak dodać w Eclipse dowolne brakujące definicje.

2008-02-10

Migracja z EJB 2.1 Entity Beans do Hibernate

Niedawno stanąłem przed koniecznością przepisania warstwy dostępu do danych z Entity Beans na Hibernate. Baza danych nie mogła być zmieniana, więc nowe klasy mapowane przez Hibernate musiały mieć dokładnie te same atrybuty i powiązania co dotychczasowe Entity Beans oraz musiały radzić sobie z typami danych w istniejących tabelach. Wszystko szło gładko do momentu kiedy trafiłem na atrybut mapowany na kolumnę typu BLOB (poniżej notacja XDocletowa):

/**
* @ejb.persistence column-name="NAZWA" jdbc-type="BLOB"
*/
public abstract String getNazwa();

Atrybut jest typu String, więc spodziewałem się że w bazie będą zapisane po prostu ciągi bajtów uzyskane metodą getBytes(). Jednak po sprawdzeniu istniejących wartości okazało się, że są to zserializowane obiekty i to nie klasy String, ale org.jboss.invocation.MarshalledValue (aplikacja działa na JBossie). Konieczne było więc napisanie odpowiedniej implementacji Hibernate'owego interfejsu UserType. Pomocny okazał się - jakże by inaczej - Spring, dostarczając bazowej klasy AbstractLobType:

public class MarshalledStringType extends AbstractLobType {
private static final int[] TYPES = { Types.BLOB };

protected Object nullSafeGetInternal(
ResultSet rs, String[] names,
Object owner, LobHandler lobHandler)
throws SQLException, IOException, HibernateException {

if (names.length != 1) {
throw new HibernateException("invalid column names");
}
Blob blob = rs.getBlob(names[0]);
try {
ObjectInputStream ois = new ObjectInputStream(blob.getBinaryStream());
MarshalledValue mv = (MarshalledValue) ois.readObject();
return mv.get();
} catch (IOException e) {
throw new HibernateException(e);
} catch (ClassNotFoundException e) {
throw new HibernateException(e);
}
}

protected void nullSafeSetInternal(
PreparedStatement ps, int index, Object value, LobCreator lobCreator)
throws SQLException, IOException, HibernateException {

MarshalledValue mv = new MarshalledValue(value);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(mv);
oos.close();
baos.close();
lobCreator.setBlobAsBytes(ps, index, baos.toByteArray());
}

public Class returnedClass() {
return String.class;
}

public int[] sqlTypes() {
return TYPES;
}
}

Aby nowy typ był widoczny dla Hibernate wystarczy jedna adnotacja, najlepiej w pliku package-info.java w pakiecie nadrzędnym dla klas modelu danych:

@org.hibernate.annotations.TypeDefs({
@org.hibernate.annotations.TypeDef(
name = "marshalledString",
typeClass = MarshalledStringType.class
)
})
package pakiet.nadrzedny.modelu.danych;

Od tego momentu marshalledString może być używany tak samo jak wszystkie standardowe typy dostępne w Hibernate:

@Basic
@Type(type = "marshalledString")
@Column(name = "NAZWA")
public String getNazwa() {
return nazwa;
}

2008-02-08

Problem z adnotacją @Autowire w Springu 2.5.1

Bug ujawnia się dość specyficznej sytuacji: jeżeli używamy automatycznego rozwiązywania zależności (autowiring) opartego na adnotacjach, mamy komponent nie będący singletonem i mający przynajmniej jeden atrybut będący kolekcją. W poniższym przykładzie:
public class TestBean {
   private List<TestDep> deps;

   @Autowired
   public void setTestDeps(List<TestDep> deps) {
       this.deps = deps;
   }
}


public class TestDep {
}


<beans>
   <context:annotation-config/>

   <bean id="testBean" class="test.TestBean" scope="prototype"/>

   <bean id="testDep" class="test.TestDep"/>
</beans>


public class Test {
   public static void main(String[] args) {
       ClassPathXmlApplicationContext ctx = ...
       ctx.getBean("testBean");
       ctx.getBean("testBean");
   }
}
pierwsze wywołanie ctx.getBean("testBean") zadziała poprawnie, ale drugie (i każde następne) zgłosi wyjątek IllegalArgumentException: argument type mismatch. Problemy powoduje kod odpowiedzialny za cache'owanie referencji do komponentów w klasie wewnętrznej AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement. Wpisałem zgłoszenie do JIRY (numer SPR-4438) i po 39 minutach (!) błąd został poprawiony, a poprawka włączona do wersji 2.5.2. Rewelacja. [aktualizacja 2008.03.04] Wersja 2.5.2 została wydana wczoraj i AutowiredAnnotationBeanPostProcessor działa w niej poprawnie.

2008-01-17

Znacznik <script> w IE7

Straciłem ładnych parę godzin szukając przyczyny dlaczego aplikacja GWT jest niewidoczna w IE7. Działała bez problemu w Firefoksie i Safari, a w Internet Explorerze wyświetlana była pusta strona. Ponieważ to GWT, to najpierw sprawdziłem kod w Javie, potem wygenerowane JavaScripty - nic podejrzanego nie było widać. Ostatecznie okazało się że problem tkwi w stronie, na której aplikacja jest umieszczona. IE7 poniższy zapis traktuje jako błędny i ignoruje go:
<script language="javascript" src="gwt.js"/>
Wystarczy dodać znacznik zamykający:
<script language="javascript" src="gwt.js"></script>
i skrypt jest poprawnie wczytywany. Po tej historii sprawdziłem stronę walidatorem W3C i rzeczywiście:
The sequence <FOO /> can be interpreted in at least two different ways, depending on the DOCTYPE of the document. For HMTL 4.01 Strict, the '/' terminates the tag <FOO (with an implied '>'). However, since many browsers don't interpret it this way, even in the presence of an HMTL 4.01 Strict DOCTYPE, it is best to avoid it completely in pure HTML documents and reserve its use solely for those written in XHTML.

2008-01-10

Groovy i Hibernate w jednym stali domu

Postanowiłem w pewnej Bardzo Dużej Aplikacji Webowej podnieść wersję Groovy z 1.0 na 1.5. Bo w 1.5 są adnotacje, typy generyczne, typy wyliczeniowe oraz jakże mile widziane w naszej korporacji "significant performance gains".

Sama zmiana wersji jest banalna. Projekt jest budowany Mavenem, więc zmieniamy w pom.xml wersję z 1.0 na 1.5.1 i przy okazji identyfikator grupy z groovy na org.codehaus.groovy (reorganizacja w centralnym repozytorium). Potem mvn install i za chwilę mamy gotową aplikację. Aplikację, która nie chce się deployować.

Okazuje się, że Groovy 1.5, a konkretnie znajdująca się w jego zależnościach biblioteka ASM 2.2 wywołuje konflikt z cglib 2.1_3. Cglib jest wykorzystywana przez Hibernate, a w rzeczonej aplikacji Hibernate jest kluczową technologią. Po zmianie ASM na wersję 1.5.3 działającą z cglibem przestaje działać Groovy, więc nie tędy droga. Rozwiązaniem jest użycie wersji cglib-nodep, która nie wymaga ASMa (a dokładnie klasy ASMowe, przeniesione do innych pakietów, ma włączone do swojego kodu).

Pewnym problemem jest Maven - artefakty cglib 2.1.3, asm 1.5.3 i asm-attrs 1.5.3 są w zależnościach Hibernate. O ile zmianę wersji ASMa możemy wymusić za pomocą dependency management:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-attrs</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
</dependencyManagement>

to zmiana cglib na cglib-nodep wymaga wykluczenia cglib z zależności Hibernate i dodania cglib-nodep jako nowej zależności:
<dependencies>
<dependency>
<groupid>org.hibernate</groupid>
<artifactid>hibernate</artifactid>
<exclusions>
<exclusion>
<groupid>cglib</groupid>
<artifactid>cglib</artifactid>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupid>cglib</groupid>
<artifactid>cglib-nodep</artifactid>
<version>2.1_3</version>
</dependency>
</dependencies>

Nie jest to rozwiązanie do końca eleganckie. Konieczna jest modyfikacja (i późniejsze pilnowanie) zależności Hibernate we wszystkich projektach wchodzących w skład aplikacji. Jednak w następnej wersji (3.2.6) problem ma być załatwiony - Hibernate będzie wykorzystywać cglib 2.2 i ASM 2.2 (zgłoszenie HHH-2875).

[aktualizacja 2008.03.03]

8. lutego została wydana wersja 3.2.6, jednak nie ma w niej zapowiadanej poprawki - została przesunięta na wersję 3.3, czyli bliżej nieokreśloną przyszłość.

2008-01-09

ASUS A696

Od około czterech tygodni jestem szczęśliwym :-) posiadaczem ASUSa MyPal A696. Zabawka ma odbiornik GPS (to główny powód zakupu), kartę Wi-Fi i moduł Bluetooth, działa pod systemem Windows Mobile 6.0 (niespodzianka, bo na stronie producenta cały czas jest 5.0). Jednak nie obyło się bez problemów.

PDA od początku nie rozpoznawał karty SD - po każdym wyłączeniu i włączeniu pojawiał się irytujący komunikat o nieznanej karcie. Żeby było śmieszniej taki sam komunikat pojawiał się nawet wtedy, gdy karty w ogóle nie było w slocie. Po zerknięciu na stronę ASUSa okazało się że problem jest znany i występuje w firmware V03.0720.00. Do ściągnięcia jest patch który podnosi wersję do V03.0735.00 i łata przy okazji kilka innych dziur.
Po kilku dniach objawiła się rzecz poważniejsza: przestała działać karta Wi-Fi. Padała stopniowo - początkowo zdarzało się zrywanie połączenia (nawet bardzo blisko routera), potem połączenie znikło na dobre a system przestał w ogóle widzieć Wi-Fi. Szczęśliwie wada ujawniła się w ciągu 10 dni od zakupu - w takiej sytuacji ASUS wymienia sprzęt na nowy bez zbędnych pytań.

Drugi A696 miał od razu zainstalowany najnowszy firmware V03.0735.00 i jak dotąd (puk puk) działa idealnie: karta 2GB Extreme III jest rozpoznawana, Wi-Fi łapie sygnał w całym mieszkaniu. Nie miałem jeszcze okazji pojechać gdzieś dalej z GPSem, ale nie sądzę aby miały być jakieś problemy - wystawiony za okno bez problemu łapie fixa.

Generalnie urządzenie warte jest swojej ceny. Planując zakup brałem pod uwagę także Mio P560 - bardzo podobne możliwości do A696 i trochę tańszy. Na korzyść ASUSa przemawia czas pracy baterii (w testach, ale na czymś się trzeba oprzeć), trochę wydajniejszy procesor i - last but not least - wygląd zewnętrzny.

[aktualizacja 2008.01.27]

Sprawdziłem doświadczalnie jak sprawuje się bateria. Po pełnym naładowaniu wytrzymała ponad 4 godziny używania GPSa (AutoMapa, jasność ekranu około 40%), godzinę z włączonym Wi-Fi i 2 dni czuwania. Moim zdaniem zupełnie dobrze.

© The Useful Pot To Keep Things In
Maira Gall