Java 6 ile gelen Scripting Desteği – Java Scripting

Artık scripting dilleri yazılım dünyasında çok önemli bir yere sahip ve her alanda  karşımıza çeşitli şekillerde çıkmaya devam ediyor. Bu kadar hızlı gelişen scripting dillerine karşın, Javanın sessiz kalması tabiki düşünülemezdi. Peki Java, scripting dillerini kullanabilmek ve entegre edebilmek için ne gibi bir çözüm sağlıyor?  Bu yazımızda bu konuya cevap arayacağız.

Scriptleme dillerinin belli başlı özellikleri

Günümüzde scriptleme (scripting) dilleri artık çok popüler bir hale geldi ve gittikçe de büyüyen bir kullanıcı grubuna sahip. Bir kaç scriptleme dili örneği vermek istersek Javascipt, PHP, Ruby ve Python sayabiliriz. Scriptleme dillerinin bu kadar popüler olmasının başlıca nedenleri şunlardır:

–          Çoğu scriptleme dilleri dinamik tiplidir (dynamic typed). Yani kullanmak istediğiniz bir değişkeni (variable) deklare (declare) etmeden kullanabilmek veya değişken içine her tipte veri yazabilmek anlamına gelmektedir.

–          Scriptleme dillerinde bir derleme (compile) olmadığından dolayı kodlar direk yorumlanabilmektedir(interpreted). Yani değiştir-derle-çalıştır yerine değiştir-çalıştır oluyor. Böylelikle yazılımcıların verimliliği artmaktadır.

–          Normal programla dillerine kıyasla daha esnek ve kolay bir programla modeli sunmaktadır. Bu sayede normal bir dilde örneğin 20 satırda yazılabilen bir kodu, scriptleme dillerinde 1 satırda yazmak sözkonusu olabilmektedir.

Scriptleme dilleri ve Java

Scriptleme dillerine Java penceresinden bakarsak, Java için ne kadar büyük bır avantaj sağlıyabileceğini görebiliriz. Örneğin, Java içerisinden herhangi bir scriptleme dilinde yazılmış bir kodu  çalıştırmak veya herhangi bir script içerisinden Java sınıflarını kullanmak.

Bu entegrasyonu sağlayabilmek için günümüze kadar değişik yöntemler denenmiş ve uygulamalar yazılmıştır. Örneğin Rhino, Jacl, Jython, BeanShell, Jruby ve diğerleri.  Bu konuda belli bir standart olmadığından dolayı her uygulama geliştirici kendine göre bir entegrasyon arayüzü geliştirmiştir.

Java SE 6 ve scriptleme desteği

Bu sorunları çözebilmek için, Sun şirketi 2006 yılında çıkarttığı Java SE 6 spesifikasyonuyla beraber gelen Scripting desteğini  (JSR 223: Scripting for the JavaTM Platform ) [1] çıkarmıştır.

Bu scriptleme desteği, Java teknolojisini ve scriptleme dillerini entegre eden standart bir framework ve yazılım geliştirme arayüzü sunmaktadır.  Böylelikle şunlar mümkün olabilecektir:

–          Standart arayüzü sayesinde istenilen her scriptleme dili için bir entegrasyon modülü yazmak.

–          Scriptleme dilleri içinden direk olarak Java objelerine ulaşmak ve kontrol etmek.

–          Scriptleme kullanarak web projeleri geliştirmek.

–          Dışarıdan eklenen herhangi bir script dosyasını direk Java içerisinde çalıştırıp kullanabilmek.

Kullanabileceğimiz scriptleme dilleri

Oracle (önceki Sun) şirketinin Java SE 6 spesifikasyonunun imlementasyonunda standart olarak Rhino: Javascript for Java modülü eklenmiştir. Bunun yanında bir çok scriptleme dili için ekler yazılmıştır. Bunlardan bazıları şunlardır: PHP, Python, JavaFX, SmallTalk, Ruby, Groovy, Jelly, XSLT.

Tüm desteklenen scriptleme dillerinin listesine Dev Java sitesinden [2] ulaşabilirsiniz.

Scriptleme destek arayüzünün detayları

Scriptleme desteğiyle beraber gelen tüm sınıflar javax.script paketi  (package) içinde bulunabilir. Bu sınıflar ve arayüzler şunlardır:

Arayüzler Siniflar
Bindings SimpleBindings
Compatible CompiledScript
Invocable ScriptEngineManager
ScriptContext SimpleScriptContext
ScriptEngine AbstractScriptEngine
ScriptEngineFactory ScriptException

Tüm Scripting API bunlardan ibarettir.

Küçük bir script örneği – merhaba dünya

Bu API kullanmayı ScriptEngineManager sınıfı ile başlıyoruz. Bu sınıf bize bulunduğumuz ortamda hangi ScriptEngine (scriptleme dil modülleri) olduğunu bildirecektir.  Sonra istediğimiz bir ScriptEngine objesiyle kullanmak istediğimiz scriptleri çalıştırabiliriz.

Yukarıda anlatılanları uygularsak karşımıza şöyle bir kod çıkıyor:

[sourcecode language=”java”] ScriptEngineManager manager = new ScriptEngineManager():
ScriptEngine javaScriptEngine = manager.getEngineByName("JavaScript"):
try {
javaScriptEngine.eval("print(‘Merhaba Dunya’)"):
} catch (ScriptException ex) {
//print exception
}
[/sourcecode]

Örnek 1

Bu kodu inceleyecek olursak 2. satırda manager objesinden bize JavaScript scriptleme modülünü vermesini istiyoruz.  4. satırda da eval metoduyla javascript scriptini çalıştırıyoruz. Bu kod çalıştığı anda console çıktısında bize Merhaba Dunya yazısını yazacaktır. Script dillerinde printlenen her değer Javada console içine yazılır.

Sistemdeki script engine leri görüntüleme

Örnek 1’deki  4. satırda sistemden JavaScript adındaki engine isteniyor. Peki sistemde hangi dillerin modülleri mevcut olduğunu nasıl görebileceğiz? Bunu öğrenmek için ScriptEngineFactory sınıfını kullanıyoruz.

[sourcecode language=”java”] ScriptEngineManager mgr = new ScriptEngineManager():
List<ScriptEngineFactory> factories = mgr.getEngineFactories():
for (ScriptEngineFactory factory : factories) {
System.out.println("ScriptEngineFactory Info"):
String engName = factory.getEngineName():
String engVersion = factory.getEngineVersion():
String langName = factory.getLanguageName():
String langVersion = factory.getLanguageVersion():
System.out.printf("\tScript Engine: %s (%s)\n", engName, engVersion):
List<String> engNames = factory.getNames():
for (String name : engNames) {
System.out.printf("\tEngine Alias: %s\n", name):
}
System.out.printf("\tLanguage: %s (%s)\n", langName, langVersion):
}
[/sourcecode]

Örnek 2

Bu kodu çalıştırdığımızda sistemde hangi script modüllerinin olduğunu görüyoruz:

ScriptEngineFactory Info

Script Engine: Mozilla Rhino (1.6 release 2)

Engine Alias: js

Engine Alias: rhino

Engine Alias: JavaScript

Engine Alias: javascript

Engine Alias: ECMAScript

Engine Alias: ecmascript

Language: ECMAScript (1.6)

Console 1

Sisteme yeni bir script dili ekleme

Şu an da sistemimizde sadece JavaScript yüklü. Yeni bir script engine eklemek istersek yapmamız gereken şunlar:

–          Scripting Java.net sitesinin [3] documents bölümünden jsr223-engines.zip dosyasını indirmek.

–          Bu zip dosyasının içinde her desteklenen script dili için bir klasör bulunur. Eklemek istediğiniz script dilinin klasörünü açın ve içindeki build klasörünün içindeki –engines.jar dosyasını projenizin classpath bölümüne ekleyin.  Örnek olarak Jruby dosyasının içindeki jruby-engines.jar dosyasını proje classpath ekledim.

–          Yukarıdaki kodumuzu tekrar çalıştırdığımızda sistemde yeni bir script engine factory eklendiğini görürüz. Bakınız Console 2.

–          Her ne kadar jruby sistemimize eklense de çalışabilmesi için jruby ye ait çalışma jar dosyalarını bulup, bunları da classpath’ımıza eklememiz gerekiyor. Bunu jruby sitesinden [4] yapabilirsiniz. İndirdiğiniz package içerisinde ki jruby.jar classpath’a ekleyin.

–          Artık Java içerisinden herhangi bir jruby scriptini çalıştırabiliriz.

ScriptEngineFactory Info
Script Engine: Mozilla Rhino (1.6 release 2)
Engine Alias: js
Engine Alias: rhino
Engine Alias: JavaScript
Engine Alias: javascript
Engine Alias: ECMAScript
Engine Alias: ecmascript
Language: ECMAScript (1.6)
ScriptEngineFactory Info
Script Engine: JRuby Engine (1.1.4)
Engine Alias: jruby
Engine Alias: ruby
Language: ruby (1.8.6)

Console 2

Script dosyasını çalıştırmak

Kodumuzun dışında bulunan bir script dosyasını da çalıştırmamız mümkün.  Bakınız Örnek 3ç

[sourcecode language=”java”] ScriptEngineManager engineMgr = new ScriptEngineManager();
ScriptEngine engine = engineMgr.getEngineByName("ECMAScript");
InputStream is = DosyaCalistirma.class.getResourceAsStream("test.js");
try {
Reader reader = new InputStreamReader(is);
engine.eval(reader);
} catch (ScriptException ex) {
// print exception
}
[/sourcecode]

Örnek 3

Değişkenleri ve metodları  kontrol etmek

Scriptleri çalıştırırken her türlü değişkenlere etki edebiliriz. Örnek 4’te de görüldüğü gibi Java içerisindeki bir değişkeni script içine yolluyoruz ve script içinde kullanabiliyoruz.

[sourcecode language=”java”] ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// degisken yaratiyoruz
File f = new File("test.txt");
// degiskenimizi script icine ayni isim altinda gonderiyoruz
engine.put("file", f);
//script icinde degiskenimizi kullaniyoruz
engine.eval("print(file.getAbsolutePath())");
[/sourcecode]

Örnek 4

Değişkenlerin yanında metodları da direk çağrmamız mümkün.  Mesela script içinde bulunan bir parametreli metodumuzu çağırmamız mümkün. Bakınız Örnek 5.

[sourcecode language=”java”] ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
// javascript icerisinde yazdigimiz bir metod
String script = "function hello(name) { print(‘Hello, ‘ + name); }";
engine.eval(script);
// metod cagirmak icin Invocable arayuzune cast ediyoruz
Invocable inv = (Invocable) engine;
// metodumuzu parametre gondererek cagiriyoruz
inv.invokeFunction("hello", "Baris Dere" );</td>
[/sourcecode]

Örnek 5

Hello Baris Dere

Console 3

Scriptler içinde Java sınıflarını kullanmak

Yazımızdaki tüm örneklerde hep Java içerisinden JavaScript kullandık. Şimdi bunun tam tersini yapacağız. Yani script içinde java sınıflarını kullanacağız. İlk örneğimizde (Bakınız Örnek 6) java awt sınıflarını kullanıp bir windows açacağız.

[sourcecode language=”java”] // Import Java packages and classes
// like import package.*; in Java
importPackage(java.awt);
// like import java.awt.Frame in Java
importClass(java.awt.Frame);
// Create Java Objects by "new ClassName"
var frame = new java.awt.Frame("hello");
// Call Java public methods from script
frame.setVisible(true);
// Access "JavaBean" properties like "fields"
print(frame.title);</td>
[/sourcecode]

jstojava.js

[sourcecode language=”java”] ScriptEngineManager engineMgr = new ScriptEngineManager();
ScriptEngine engine = engineMgr.getEngineByName("ECMAScript");
InputStream is = DosyaCalistirma.class.getResourceAsStream("jstojava.js");
try {
Reader reader = new InputStreamReader(is);
engine.eval(reader);
} catch (ScriptException ex) {
// print exception
}
[/sourcecode]

Örnek 6

Kendi script dilini yazmak

Kendi script dilinizi yazmak çok kolay. Tek yapmanız gereken ScriptEngine ve ScriptEngineFactory arayüzleri için kendi implementasyonunuzu yazmak.

Sonuç

Bu yazımızda Java SE 6 ile gelen Scriptleme desteğini inceledik. Görüldüğü gibi artık yazdığımız kodları sadece Java’da değilde, istediğimiz scripting dillerinde de yazmak ve hepsini bir arada çalıştırmak mümkün. Scripting dillerinin popüleritesinin her geçen gün arttığını düşünürsek, bunun Java için büyük bir avantaj olduğunu söyleyebiliriz. Belki Java dili istenildiği hızda bir gelişme kaydedemiyor olabilir (örnek closures), ama yine de bunun gibi eklentilerle Java yı daha geniş bir perspektife koymak mümkün olabilir.

[1] JSR 223: Scripting for the JavaTM Platform – http://jcp.org/en/jsr/detail?id=223
[2] Scripting Java Source – https://scripting.dev.java.net/
[3] Scripting Java.net documents – https://scripting.dev.java.net/servlets/ProjectDocumentList
[4] Jruby web sitesi – http://jruby.codehaus.org/
http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/
http://download.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html

Share this Story

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *