15 maja 2009

Rozwiązywanie niezgodności binarnych z maven-shade-plugin

Moim ciągle niezrealizowanym zadaniem jest poznanie dwóch rozwiązań do zmiany bajtkodu (klas javowych w postaci binarnej) - asm i cglib. Pamiętam wystąpienie Piotra Kobzdy na ten temat podczas Javarsovii 2007, w którym chciałem uczestniczyć bardziej aktywniej niż to było mi dane - obowiązki organizatora i moja wrodzona natura gaduły dały się poznać. Skończyło się na krótkich urywkach wystąpienia Piotra i temat zamarł jako zbyt zaawansowany, a może po prostu z powodu niewielkiej wartości praktycznej - w końcu asm/cglib nie są tak często wykorzystywane wprost jak chociażby równie ciekawe rozwiązania typu Grails. Jest wiele podobnych tematów, których znajomość pomaga, ale nie będąc warunkiem koniecznym odkłada się je na półkę na bliżej nieokreśloną przyszłość. Możnaby mnożyć takich perełek bez liku, chociażby programowanie w języku funkcyjnym, albo nawet tak podstawowe jak wzorce projektowe. Znajomość innego myślenia pomaga w zrozumieniu problemów, w których nie mają zastosowania, ale przez swoją odmienność prowokują do bardziej wytężonego wysiłku umysłowego i wtedy, nieoczekiwanie otwierają się nieużywane dotąd obszary naszego umysłu. Przypomina mi to rozmowę z nowicjuszami, których często zbywa się sądząc, że mogą jedynie zająć czas, ale którzy, przez swoje nietypowe pytania dotykające podstaw, okazują się być idealnymi katalizatorami myślenia - jeśli tylko wytrwamy z ich niewiedzą możemy paradoksalnie uporządkować sobie swoją (nie)wiedzę. Paradoksalnie, Ci niewprawieni w boju, owi nowicjusze nie są jeszcze tak ograniczeni jak my - wiedza rozwija, ale jednocześnie nakłada na nas swoje ograniczenia.

Zaletą pracy przy projektach otwartych jest możliwość rozwiązywania problemów na długo wcześniej niż pojawią się we własnych projektach komercyjnych. Mamy możliwość doświadczenia innego sposobu myślenia i pojawiają się zaskakujące rozwiązania - zaskakujące swoją prostotą i odmiennością. To każdy lubi.

Powrót do mojej działalności w Apache OpenEJB zacząłem od czyszczenia mojego backlogu. Lista nie jest pokaźna, ale niezwykle leciwa. Jednym z zadań było rozwiązanie problemu niezgodności binarnej ASM między wersjami 1.5.3 a nowszymi, które wykorzystywane są przez OpenEJB i inne projekty, np. wszechobecny Hibernate, które mogłyby być użyte wspólnie z nim w ramach pojedynczej aplikacji, co nieuchronnie prowadzi do błędu:

java.lang.NoSuchMethodError: org.objectweb.asm.ClassReader.accept(Lorg/objectweb/asm/ClassVisitor;I)V

Jest to odprysk prac nad wsparciem dla @ApplicationException - Optional @ApplicationException inheritance, gdzie wymagana jest nowa wersja Apache XBean, która przychodzi z asm/cglib, więc w połączeniu ze wspomnianym Hibernate może narobić niezłego zamieszania. Jest kilka opcji rozwiązania i panowie ze SpringSource opisali trzy - ASM version incompatibilities, using Spring @Autowired with Hibernate. Jeśli Twój projekt jest oparty na Apache Maven możesz skorzystać z kolejnego rozwiazania opartego na wtyczce maven-shade-plugin, co opisałem w artykule Rozwiązywanie niezgodności binarnych z maven-shade-plugin. Znajdziesz w nim opis problemu i przedstawienie rozwiązania. Z wiadomych względów zdecydowanie polecam! :)