2010-10-26

Krótko

Nabyłem drogą kupna Photoshopa (Elements oczywiście). Wiem: ekstrawagancja i burżuazja, ale czasami mi się to zdarza. Ale ja nie o tym chciałem. Rzeczony Photoshop został wysyłany przez Amazon UK DHLem za darmo (od niedawna Free Super Saver Delivery obejmuje też Polskę) i kosztował 280 PLN. W naszym rodzimym sklepie, np. przysłowiowym Vobisie kosztuje 399 PLN. Rrrwa mać po trzykroć.
Share:

2010-10-17

Icon Finder

Nie raz i nie dwa pisząc program lub tworząc stronę internetową potrzebowałem różnego rodzaju ikon. Podstawowe kryteria, które musiały spełniać to: estetyczne, spójne i last but not least legalne. Bardzo ładnym i obszernym zestawem są Crystal Icons (licencja LGPL), ale jednak nie do wszystkiego pasują - są odrobinę zbyt śliczne. Drugi zestaw z którego tu i ówdzie korzystałem to Mini Icons ze strony famfamfam.com - prościutkie, małe ikonki idealne do użycia w aplikacjach webowych, ale jest ich tylko 144 i nie zawsze znajdzie się to czego potrzeba. Dzisiaj trafiłem na stronę Icon Finder. W tej chwili jest tam 645 zestawów, 188325 ikon! I przede wszystkim możliwość wygodnego wyszukiwania bo wszystkie ikonki mają przypisane tagi (np. "red", "arrow", "left"). Mój ulubiony na dzień dzisiejszy zestaw to Simplico (licencja Creative Commons).
Share:

2010-08-26

Groovy 1.7.0 i Spring

W jednej z aplikacji które popełniłem, używam skryptów Groovy jak kontrolerów Spring MVC. Jest to wygodne w sytuacji, kiedy kod kontrolera często się zmienia a nie ma możliwości restartu całej aplikacji. Dzięki poniższej definicji:

komponent some.Controller będzie automatycznie przeładowywany (czyli skrypt będzie ponownie kompilowany) jeżeli plik źródłowy Script.groovy się zmieni (ale nie częściej niż podany czas - tutaj 1000 ms). Wszystko działało tak jak powinno do momentu upgrade'u Springa do wersji 3.0.0.RELEASE - wtedy aplikacja przestała zauważać zmiany w skryptach. Uznałem, że chwilowo mogę bez tego żyć a w wersji 3.0.1 pewnie poprawią. Kiedy jednak po kolejnych uaktualnieniach doszedłem do wersji 3.0.3 i dalej nie było ani trochę lepiej, zacząłem intensywniej szukać. Okazało się, że Spring jest niewinny a problemy sprawia sam Groovy, którego wersję podniosłem do 1.7.0 na fali ogólnego uaktualniania aplikacji (w zależnościach Springa jest 1.6.3). Aby dynamiczne przeładowywanie zaczęło znowu działać trzeba albo cofnąć się do wersji 1.6.x, albo użyć najnowszego Groovy (w tej chwili 1.7.4). Dla zainteresowanych zgłoszenie w JIR-ze GROOVY-3981.
Share:

2010-08-15

SyntaxHighlighter

Edycja listingów we wpisach zamieszczanych na Bloggerze to makabra. Sam edytor nie jest szczytem marzeń, ale prawdziwy problem to psucie wcięć. Nawet jeżeli umieszczę listing w tagach <pre> które teoretycznie powinny zachowywać formatowanie, to przejście w Bloggerowym edytorze z zakładki Edytuj kod HTML na Nowy post zjada mi co najmniej jedną spację z wcięcia. Początkowo myślałem że robię coś nie tak, ale w sieci można znaleźć sporo informacji o tego typu problemach. Nie znalazłem rady na zjadanie spacji (anyone?), ale znalazłem sposób na formatowanie (dzięki któremu mogę w miarę komfortowo pisać tylko w HTMLu): SyntaxHighlighter. Jest to zestaw JavaScriptów i arkuszy stylów, który automatycznie formatuje listingi w większości popularnych języków programowania. Wystarczy dołączyć do strony odpowiednie skrypty i style (dla ciekawych: prawy przycisk myszy i View Page Source) a potem umieścić listing w tagu <pre> z zaznaczeniem sposobu formatowania:
<pre class="brush: java">
public class Test {
    private String a;
    public Test() {
        // konstruktor
    }
}
</pre>
Efekt wygląda tak:
public class Test {
    private String a;
    public Test() {
        // konstruktor   
    }
}
Jedyne niedociągnięcie jakie zauważyłem, to niepotrzebne wyświetlanie pionowego scrolla w przeglądarkach opartych na silniku WebKit (Safari, Google Chrome).

[aktualizacja 2010.08.16]

Dodałem SyntaxHighlightera do posta o Google App Engine. Very nice indeed.
Share:

2010-08-08

Google App Engine

Google App Engine (for Java) umożliwia uruchamianie aplikacji webowych na serwerach Google. Używając jednego konta można zarejestrować do 10 aplikacji, każda z nich może wykorzystywać do 1GB przestrzeni dyskowej, po 1GB transferu wychodzącego i przychodzącego oraz 6.5 godziny znormalizowanego 1) czasu procesora na dobę. I to wszystko za darmo. Całkiem nieźle, prawda? Jest jednak jedno ale: Google'owa maszyna wirtualna Javy i serwer aplikacji mają trochę ograniczeń, na które można trafić próbując uruchomić coś więcej niż "Hello World".

Nie wnikając w zbędne szczegóły: moja aplikacja miała rejestrować obiekty w bazie danych (za pośrednictwem JPA) oraz udostępniać je w postaci zserializowanej do XMLa. Trafiłem na kilka mniej lub bardziej poważnych problemów.


[1] Klasa utrwalana za pomocą JPA nie może być powiązana z kilkoma obiektami tego samego typu. W poniższej sytuacji:
@Entity
class A {
}

@Entity
class B {
@ManyToOne
A pole1;
@ManyToOne
A pole2;
}
dostaniemy wyjątek:
Error in meta-data for B.pole2: Class B has multiple relationship fields of type A: pole1
and pole2. This is not yet supported.


[2] Nie jest obsługiwana strategia dziedziczenia SINGLE_TABLE. W przykładzie:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
class A {
}

@Entity
class B extends A {
}
dostaniemy wyjątek:
Found inheritance strategy 'SINGLE_TABLE' on B.  This strategy is not supported in this
context.

[3] Google App Engine dopuszcza jako identyfikatory obiektów typy Long, String oraz własny typ com.google.appengine.api.datastore.Key. Jednak gdy obiekt ma być powiązany z innym:
@Entity
class A {
@Id
Long id;
}

@Entity class B {
@ManyToOne
A a;
}
jego klucz nie może być typu Long. W powyższym przykładzie dostaniemy wyjątek:
Cannot have a java.lang.Long primary key and be a child object


[4] Nie jest obsługiwane zachłanne wczytywanie powiązanych obiektów. Przy mapowaniu:
@Entity
class A {
}

@Entity
class B {
@ManyToOne(fetch = FetchType.EAGER)
A a;
}
serwer zapisze do logu ostrzeżenie:
WARNING: Meta-data warning for B.a: The datastore does not support joins and therefore
cannot honor requests to eagerly load related objects.
The field will be fetched lazily on first access.
i zgodnie z jego treścią, obiekt powiązany trzeba będzie jawnie doczytać.


[5] Niedostępna jest klasa sun.reflect.ReflectionFactory, która wbrew nazwie nie jest specyficzna dla Sunowskiej implementacji JVM (jest dostępna także w maszynach wirtualnych IBMa i Apple). Co prawda nie próbowałem jej używać bezpośrednio, ale pośrednie owszem. Próba wykorzystania biblioteki XStream do serializacji obiektów do XMLa kończy się wyjątkiem:
java.lang.NoClassDefFoundError: sun.reflect.ReflectionFactory is a restricted class.


[6] W niektórych przypadkach uprawnienia nie pozwalają na akcje, które w typowych maszynach wirtualnych są dopuszczalne. Przykładem może być dziedziczenie z klasy java.io.ObjectOutputStream (wykorzystywane np. przez Apache Wicket i XStream) - App Engine zgłasza wyjątek:
java.security.AccessControlException: access denied
(java.io.SerializablePermission enableSubclassImplementation)


(*)Znormalizowana jednostka zużycia mocy obliczeniowej jest - dość mgliście - określona jako wydajność 1.2 GHz procesora z serii x86 Intela.
Share: