02 lipca 2009

Z rozdziału 11. o uruchamianiu kodu Groovy z Java i na odwrót w "Programming Groovy"

W rozdziale 11. "Working with Scripts and Classes" w "Programming Groovy: Dynamic Productivity for the Java Developer" dowiadujemy się o uruchamianiu skryptów/aplikacji Groovy (ogólnie zwanych kodem Groovy) z poziomu aplikacji Java i na odwrót. Skryptem Groovy nazwiemy plik z kodem Groovy, który nie jest zawarty w ramach definicji klasy podczas, gdy kiedy jest, mówimy o aplikacji Groovy. Jeśli korzystamy ze skryptów Groovy, ich wywołanie z poziomu innego kodu Groovy będzie wymagało skorzystania z GroovyShell, podczas gdy dla kodu w Javie z motoru skryptowego JSR-223.

Kiedy uruchamiamy kod Groovy za pomocą polecenia groovy, kod jest kompilowany do bajtkodu w pamięci. Za pomocą polecenia groovyc kompilujemy do pliku .class, a później możemy wykorzystywać gdziekolwiek, gdzie korzystamy z "normalnych" klas (w końcu to jest klasa w postaci bajtkodu). Zero magii, poza dodaniem groovy-all-*.jar do ścieżki klas (CLASSPATH). I nikt się nawet nie zorientuje, że dostarczamy kod pisany w Groovy.

Uruchomienie klas Groovy z poziomu kodu Groovy wymaga jedynie umieszczenie pliku .groovy w ścieżce klas. Podczas uruchomienia Groovy przeszukuje ścieżkę w poszukiwaniu pliku o nazwie używanego typu z rozszerzeniem .groovy, a później .class.

Jeśli mamy kod Groovy w postaci pliku .groovy korzystamy z groovyc i jego funkcjonalności nazywanej współkompilacją (ang. joint compilation). Wywołujemy groovyc z opcją -j i plikami .java/.groovy, a w wyniku otrzymamy bajtkod - pliki .class. Nie jest konieczne uruchamianie kompilatora javac. Zajmie się tym groovyc. Przekazywanie parametrów do kompilatora javac jest możliwe dzięki opcji -J. Najlepiej skorzystać z rozwiązania dla narzędzia, którego używamy do organizowania pracy z projektem, np. Apache Ant, Apache Maven, czy Apache Buildr, czy jeszcze inne cudo. Wtedy konieczność dbania o konfigurację będzie wyłącznie raz i zapominamy o temacie. Kto ma to już za sobą, proszę o podzielenie się konfiguracją z resztą, np. w postaci wpisu u siebie na blogu, albo w komentarzu do tego wpisu (tym samym teraz tego nie pokażę licząc, że ktoś podejmie wyzwanie :)).

Mamy możliwość uruchomienia skryptów Groovy z poziomu Groovy dzięki metodzie GroovyShell.shell(), która zwraca wynik ostatniej instrukcji, np.:
 skrypt = """println 'Witamy w swiecie skryptu Groovy'"""
new GroovyShell().evaluate(skrypt)
albo po prostu
 evaluate(skrypt)
Przekazujemy parametry do tak wykonywanego skryptu przez obiekt binding, który przekazujemy do konstruktora GroovyShell. Przy takiej konfiguracji zmienne znane skryptowi wbudowanemu (przez kontekst przenoszony przez binding) mogą być zmieniane, jakby były przekazywane przez referencję. Jeśli chcielibyśmy odseparować zmienne wywołującego skryptu od wywoływanego, tworzymy nową instancję Binding i ustawiamy te, które chcemy przez setProperty().
 binding0 = new Binding()
binding0.setProperty('nazwa', 'wartosc')
shell = new GroovyShell(binding0)
shell.evaluate(skrypt)
Możemy przekazać parametry z linii poleceń do wywoływanego skryptu, jeśli zamiast evaluate() wykonamy go przez run().

Z poziomu kodu Java wykonujemy skrypty przez JSR-223, której implementacja dostępna jest w Java 6. Pozostawiam do zbadania na własną rękę, skoro z mechanizmem współkompilacji bądź tej kompilacji skryptu Groovy do .class możemy po prostu zająć się tematem wykonania klas Groovy, a to nie jest niczym odkrywczym. Po prostu działa. Nie zapominajmy o dodaniu biblioteki groovy-all-*.jar.