10 Şubat 2008

JBoss için Login Module Tanımlanması ve Rol Bazlı EJB Güvenliği

Java Authentication and Authorization Service (JAAS) ve EJB Güvenliği adlı yazımda JAAS'dan kısaca bahsetmiştim. JAAS'ın kullandığı bir yapı olan Login Module kavramının ne olduğuna da kısaca değinmiştim. Login Module login işleminin gerçekleştiği birimlerdir. Her sistem farklı tipte login gerçekleştirebilir. Kimisi basit kullanıcı adı ve şifre bilgileri ile bu işlemi yaparken kimisi sertifika bazlı işlem yapabilir. JBoss'da kendi içinde JAAS'ı kullanmaktadır. Bu nedenle JBoss üzerinde çalıştırdığınız EJB'lere rol bazlı erişim sağlamak istiyorsanız JBoss'un kendi sunduğu bir login modül kullanabilirsiniz yada kendiniz oluşturabilirsiniz. Burada kendimiz nasıl oluştururuz ona bakalım.

Yazacağınız login module JBoss'un sunduğu AbstractServerLoginModule abstract sınıfını extend etmelidir. Bu linkte kaynak kodunu görebilirsiniz (Ayrıca bu sınıfı kullanan JBoss login modülleri olan UsernanePasswordLoginModule ve DatabaseServerLoginModule sınıflarının kodları da incelenmesi gerekmektedir). Bu nedenle yazacağınız kod getRoleSets() ve getIdentity() metodlarını override etmelidir. Tabi bunlarla kalmamak lazım. Bir de login işlemini gerçekleştiren login() metodu var. Bu metod bu sınıfta implemente edilmiş ama biz kendimize uygun bir login modül oluşturacağımız için bu metodu da override etmemiz gerekir. Ayrıca login module ilklendirilirken kullandığınız seçenekler var ise initialize() metodunu da override etmek gerekir. Genel olarak sınıf aşağıdaki gibi olacaktır:

package com.ornek;

public class MyLoginModule extends AbstractServerLoginModule {

...

/*

burada options parametresi login modül'e verilen optionları barındırır, callbackHandler giriş bilgilerini barındırır, subject de rol bilgilerini tutar.

*/

public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {

...

}

/*

login işlemi burada gerçekleştirilir. işlem başarılı ise mutlaka süper sınıfta tanımlanmış loginOk değişkeni true değerine atanmalıdır. Aksi takdirde süper sınıftaki commit metodu çalışmaz.
*/

public boolean login() throws LoginException {

}

...

super.loginOk = true;

...

}

/*

Login olan kullanıcının role gruplarını oluşturan bir metoddur ve override edilmesi gerekir. Bu metod override edildiğinde kullanıcının role bilgilerini barındıran en azından “Roles” adında bir Group oluşturulmalıdır.

*/

protected Group[] getRoleSets() throws LoginException {

...

}

/*

Kullanıcının birincil giriş bilgisini içeren Principal nesnesini döndürür.

Bu metod genelde login metodu içinde oluşturulan Principal nesnesini döndürür.

*/

protected Principal getIdentity() {

...

}

Kendi modülünüzü yazdıktan sonra bunun Jboss’a tanıtılması gerekmektedir. Bunun için login module sınıfınızı jar haline getirin ve Jboss deploy kütüphanelerini (/server/default/lib) arasına oluşturduğunuz jar’ı kopyalayın. Daha sonra deploy konfigürasyonlarının olduğu dizin (/server/default/conf) altındaki login-config.xml dosyasını açın. Bu dosyaya kendi login modulünüzü ekleyeceksiniz. Zaten dosyanın başında nasıl yapcağınız anlatılıyor. Örneğin yukarıdaki sınıfı şu şekilde eklenebilir:





Görüldüğü üzere kendi yazacağınız login module sınıfında yukarıdaki üç metodu override etmeniz yeterli olacaktır. login metodu düzgün olarak çalıştığında ve super.loginOk = true ise süper sınıf kendi içindeki commit metodunu çalıştıracak ve kullanıcının rol bilgilerini oluşturan getRoleSets metodunu çağıracak. Bütün işlemler bittiğinde kullanıcıya ait giriş ve rol bilgilerini barındıran bir Subject nesnesi oluşturulacak. Bu nesne ejb metodları çağırılırken çağıranın rol bilgilerinin kontrolü için kullanılacak. Örnek:

@Remote

public interface MyEJB {

public void myMethod();

}


@SecurityDomain(“MyLoginModule”)

@Stateless

public MyEJBImpl implements MyEJB {

@RolesAllowed(“MyRoleName”)

public void myMethod() {

...

}

}

Yukarıdaki örnekte EJB metodları çalıştırılmadan önce MyLoginModule ismindeki login modülün çalıştırılacağı ve kullanıcının girişinin gerçekleştirileceği SecurityDomain annotation’ı ile belirtilmiştir. SecurityDomain annotation’ı içine vereceğiniz login module ismi login-config.xml dosyasında tanımlı olmalıdır. Kullanıcı girişi gerçekleştirildiğinde istenilen ejb metodu çağırılır aksi takdirde hata verilir.

Bir EJB metodu olan myMethod’a sadece MyRoleName rolundeki kullanıcıların erişebileceği @RolesAllowed annotation’ı ile gösterilmiştir. Bu annotation içine birden fazla rol yazabilirsiniz @RolesAllowed(“Role1”, “Role2”, ...) şeklinde. İşte bu annotation içindeki rol bilgileri login module tarafında oluşturulan Subject nesnesinin içindeki rol bilgisiyle karşılaştırılır. Eğer Subject nesnesi bu rollerden birisini barındırıyorsa metod çalıştırılır. Aksi takdirde çalıştırılmaz.

07 Ocak 2008

Java Authentication and Authorization Service (JAAS) ve EJB Güvenliği

JAAS java uygulamaları için kimlik doğrulama ve yetkilendirme işlemlerini portatif bir şekilde yapılmasını sağlayan bir arayüzdür. JAAS'ı kullanarak kendiniz sisteme giriş yapmayı ve yetkilendirmeyi sağlayan mödüler API'ler yazabilirsiniz.
JAAS'ı herhangi bir güvenlik sisteminde kullanabilirsiniz. Örneğin; bir uygulama sunucusu kimlik doğrulamayı bir dosyadan okuyarak yapıyor olabilir yada bir veritabanından sorgulatarak ya da bir LDAP sunucusuna bağlanarak yapıyor olabilir. JAAS ile bu ortamlara ayak uydurmak hiç dert değil. Çünkü JAAS interface'lerden oluşur ve siz de bu interface'leri implemente edersiniz. Böylece kimse kimseye darılmaz.
JAAS EJB güvenliğinde sıklıkla kullanılır. Sun, JAAS'ı EJB güvenliğinde standard olarak kullanmaktadır.

Genelde JAAS modüllerinin kullanımı ile ilgili iki tip senaryo vardır:

  • Bir masaüstü uygulamanız vardır ve bu uygulamanız uzak bir uygulama sunucusuna bağlanıp sisteme giriş yapacaktır. Sisteme giriş sağlandıktan sonra da kullanıcının yetkileri oluşturulup bu yetkilerine göre sistemde hangi modüllere erişip hangi modüllere erişemeyeceği belirlenecektir. Bunun için masaüstü uygulamanız JAAS ile kullanıcının giriş bilgilerini uygulama sunucusuna iletir. Uygulama sunucusu da bu bilgileri kullanarak sisteme girişi gerçekleştirip kullanıcının rollerini oluşturur. Bundan sonraki EJB metodlarının çağırılmasında kullanıcının rol bilgilerine bakılır. Eğer yetkisi varsa izin verilir yoksa izin verilmez.
  • Bir web tarayıcı aracılığı ile sisteme giriş yapabilirsiniz. Burada da kullanıcının giriş bilgileri JSP/servlet'e aktarılır. JSP/Servlet'de bu bilgileri kullanarak sisteme girişi gerçekleştirir. Tarayıcı giriş bilgilerini aşağıdaki yöntemleri kullanarak aktarır:
    • Basic authentication
    • Form-based authentication
    • Digest authentication
    • Certificate authentication
Masaüstü uygulamaları gibi web uygulamasında da sisteme giriş gerçekleştiğinde, istemci EJB metodlarını kullancının yetkileri izin verdiği ölçüde çağırır.

JAAS'ın çalışma mantığına bakacak olursak aşağıdaki maddeler çıkabilir:
  1. İstemci yeni bir LoginContext nesnesi oluşturur. Bu sınıf JAAS tarafından sunulmuştur ve kimlik doğrulama (authentciation) sürecinden sorumludur.
  2. LoginContext nesnesi bir Configuration nesnesi alır. Bu nesnede kimlik doğrulama işleminin hangi LoginModule'ler ile yapılacağı bildirilir. Örneğin bir sistem sadece kullanıcı adı ve şifre doğrulaması istersen başka bir sistem hem kullanıcı adı-şifre hem de sertifika bazlı doğrulama isteyebilir.
  3. LoginContext Configuration nesnesine kimlik doğrulama mekanizmalarının neler olduğunu sorar.
  4. Configuration nesnesi kimlik doğrulama mekanizmalarından oluşan mekanizmalardan oluşan bir liste döndürür. Bu mekanizmaların her birine login module denmektedir. Login Module JAAS'ın sunduğu bir interface'dir. LoginModule kimlik doğrulama işleminin yapıldığı birimlerdir.
  5. LoginContext LoginModule sınıflarından birer nesne oluşturur.
  6. LoginContext oluşturulan LoginModule nesnelerini ilklendirir.
  7. İstemci kodu LoginContext nesnesi üzerinden login() metodunu çağırır.
  8. LoginContext login işlemlerini LoginModule nesnelerine devreder. Çünkü kimlik doğrulama işlemlerinin nasıl yapılacağını bu modüller bilmektedir.
  9. Sizin tarafınızdan yazılmış LoginModule nesneleri kimlik doğrulama işlemini gerçekleştirir.
  10. İşlem sonucu oluşturulan bilgiler Subject sınıfından oluşturulmuş bir nesnenin içinde saklanır. Bu nesneyi güvenli işlemler gerçekleştirmek için kullanırsınız.
  11. Bundan sonra istemci kodu EJB metodlarını çağırır ve sistem giriş bilgisi bu metod çağırımlarında otomatik olarak iletilir. Böylece uygulama sunucusu bu bilgileri kullanarak kimlik doğrulama ve yetkilendirme işlemlerini yapar.
Aşağıda yukarıdaki yapının resim olara çizilmiş halini görebilirsiniz:

Bu yazıda JAAS yüzeysel olarak incelenmiştir. Detaylı bilgi için lütfen bkz. JAAS Reference Guide

JAAS Java SE ile birlikte gelmektedir. Böylelikle ayrı bir jar indirmenize gerek yoktur.
Bir sonraki yazıda JAAS kullanarak bir JBOSS uygulama sunucusundaki EJB'lere güvenli erişmeyi sağlayan bir örnek anlatılacaktır.

Kaynak: Mastering Enterprise Java Beans 3.0

15 Ekim 2007

JBoss Binding IP Adress

Merhaba,
Bir Enterprise Java Projesi'nde çalışıyorum. Business kısmını EJB'ler üstlenmiş durumda. Uygulama sunucusu olarak JBoss 4.0.5 kullanıyorduk. Varsayılan konfigürasyonlarla bu JBoss versiyonuna aynı ağ üzerindeki herhangibir client makineden ulaşabiliyorduk. Yani business metodları çağırabiliyorduk. Fakat JSF 1.2 desteği olmadığından dolayı JBoss 4.2.1'e geçtik. Fakat bu seder EJB metodlarını çağıramaz olduk. Bu versiyonda uygulama sunucusu bir sadece bind ettiği bir IP, varsayılan 127.0.0.1, üzerinden hizmet veriyor. Bu nedenle 127.0.0.1 bind edildiğinden, yani localhost, dışarıdan erişemiyordum. Bu sorunu araştırdığımda eğer istenilen bir IP adresine bind edilmesi isteniyorsa JBoss'u "-b" seçeneği ile başlatın deniyordu. Örneğin; JBoss'un çalıştığı makinenin ağdaki IP'si 10.1.1.2 olsun. Komut satırında -b 10.1.1.2 şeklinde bir komut çalıştırırsanız JBoss 10.1.1.2 IP adresine yapılacak isteklere cevap verecektir.

18 Ağustos 2007

For each döngüsü ve Iterator

Bildiğiniz gibi Java 5 ile beraber for each döngüsü java'ya eklendi. Bu döngü ile bir collection'daki yada bir dizideki elemanlar üzerinde rahatça dolaşıp işlem yapabiliyorsunuz. Örneğin; elinizde String sınıfı tipinde nesneler barındıran "list" isminde bir List nesneniz olsun. Bu List üzerinde aşağıdaki gibi dolaşabilirsiniz:

for (String s : list) {
// s'i kullanan veya kullanmayan işlemler...
}
Bu örnekte type safety'de sağlanmış oluyor. Generics o biçim destekleniyor yani:). Bir diğer örnekte array'ler için. Örneğin elinizde A sınıfı tipinde "arr" isminde bir diziniz olsun, bu dizi üzerinde aşağıdaki şekilde dolaşabilirsiniz:

for (A item : arr) {
// item ile bir işlem yap...
}

Iterator java'da bildim bileli olan bir şey, Iterator ile Collection nesnesinin elemanları üzerinde dolaşabilir ve işlemler yapabilirsiniz ve o collection nesnesi de bu değişikliklerden etkilenir. Örneğin; içinde String nesneleri barındıran "mySet" isminde bir HashSet nesneniz bulunmaktadır. Bu set üzerinde aşağıdaki şekilde dolaşabilirsiniz.

Iterator iter = mySet.iterator();
while ( iter.hasNext() ) {
String s = iter.next();
// işlemlere devam et...
}

Gördüğünüz gibi "for each" yapısı Iterator'dan daha basit ve anlaşılır. Ancak Iterator'un pabucunun dama kaldırılmayacağını dün anladım.
İçinde oluşturduğum sınıf tipinde nesneler barındıran bir List üzerinde bir kaç işlem yapacaktım. Bu işlem de list elemanları üzerinde sırayla ilerleyip her elemanı bir koşuldan geçirip eğer koşul sağlanırsa o elemanı listeden kaldırmaktı. Bu işlemi for each ile aşağıdaki gibi yapmıştım:

List list = ...;
for (MyClass m : list ) {
if ( condition )
list.remove(m);
}

Bu kodu çalıştırdığımda java.util.ConcurrentModificationException aldım. Daha sonra aynı işlemi Iterator ile yaptım.

List list = ...;
Iterator iter = list.iterator();
while (iter.hasNext()) {
MyClass m = iter.next();
if ( condition )
iter.remove();
}

Bu kodda ise hata almadım. Nedeni kesin olarak bilmemekle beraber bildiğim kadarıyla Iterator bir Collection nesnesi içindeki elemanlar üzerinde pointer mantığıyla çalışıyor. For each'de ise böyle bir yapı yok, yani bir array gibi çalışıyor. Bu nedenle "for each" ile list üzerinde dolaşırken aynı anda bir nesneyi listeden kaldırmak istediğinizde nesnelerin indexleri değiştiğinden dolayı bu hatayı veriyor olabilir. Iterator ise kaldırılacak elemana point ettiğinden elemanı listeden kaldırıyor ve pointer'ını yeni nesne üzerinde konumlandırıyor, bir linked list mantığı. Siz ne dersiniz?

08 Temmuz 2007

Observer Pattern

Design Pattern kavramı nesne tabanlı programlama mantığında sıkça kullanılır. Belli kalıplar vardır ve bu kalıplar nesne tabanlı programlamada belli ihtiyaçlardan doğmuştur. Observer Pattern de bunlardan bir tanesidir. Bu pattern'i kafamızda canlandıracak bir örnek vermek gerekirse ki bu bir gazete sitesine abone olmak olabilir. Burada gazete sitesi bir yayıncıdır ve yeni haberler çıktığından bunları yayınlar. Siteye abone olanlar ise bu haberleri çeşitli şekillerde görürler. Bu RSS şeklinde olur, mail şeklinde olur vs.
Tanım olarak Observer Pattern kapsadığı objeler arasında one-to-many ilişkisi kurar. Böylece bir objenin durumu değiştiğinde, bu objeye bağlı diğer objelere haber verilir ve objeler kendilerini güncellerler.
Sınıf diyagramı aşağıdaki gibidir:

Diyagramda iki adet interface vardır, Subject ve Observer. Observer olacak sınıflar yani değişikliklerden haberi olacak sınıflar kendilerini bu interface'i implemente eden sınıflara, ConcreteSubject, registerObserver() metodu ile kayıt ederler. İstedikleri zamanda kendilerini removeObserver metodu ile abonelikten kaldırırlar. Subject sınıfı da observer objelerinin kim olduklarını bilmez. O sadece kendisine kayıt olan objelerin Observer interface'inin implemente ettiklerini bilir. Böylece Subject objesinde bir değişiklik olduğu zaman notifyObservers() metodu ile kendisine kayıtlı olan observer objelerinin update() metodlarını çağırır. Observer objeleri de kendilerini yenilerler. Observer Pattern sayesinde subject ve observerlar birbirlerini bilmezler, interface'ler aracılığı ile haberleşilirler. Böylece tasarım unsurlarından loosely coupled objeler sağlanmış olur. İkincisi runtime esnasında observer ollan objeler kendilerini subject sınıfına kayıt ettirebilir yada kendilerini kayıt listesinden kaldırabilirler.
Örneğin bir haber sitesinin abonelik sisteminde iki tür abonelik olsun. Bunlar Mail ve RSS olsun. Mail abonelik sisteminde abonelere haberlerin özet hali mail atılsın. RSS abonelik sisteminde haberlerin özetleri rss standardında oluşturulsun. Abonelerin rss destekli programlari oluşturulan dosyadaki değişiklikleri otomatik olarak takip ettikleri için bizim abonelere mail veya başka bir ileti atmamıza gerek yoktur. Burada iki tane arayüzümüz, Subject ve Observer, dört tane de sınıfımız olacak, Haber, HaberYayinlayicisi, MailAboneleri ve RssAboneleri. Kodlar tam olmasa da aşağıdaki gibi olabilir:

public interface Subject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}

public interface Observer {
public void update(List haberler);
}

public class HaberYayinlayicisi implements Subject {
private ArrayList observers;
private ArrayList haberler;

public HaberYayinlayicisi() {
observers = new ArrayList();
haberler = new ArrayList();
}

public void registerObserver(Observer observer) {
observers.add(observer);
}

public void removeObserver(Observer observer) {
observers.remove(observer);
}

public void notifyObservers() {
for (Observer observer : observers) {
observer.update(haberler);
}
}

public void yeniHaberlerGeldi() {
notifyObservers();
}

// bu metodu yeni haberleri olusturan baska bir sınıf cagiracak..
public void setYeniHaberler(List haberler) {
this.haberler = (ArrayList) haberler;
yeniHaberlerGeldi();
}

}

// Bu sınıf bir tane haberi gösterir.
public class Haber {
private String baslik;
private String ozet;
private String link;

public Haber() {}

// setters-getters, constructors

....
}

// Observer interface'ini implemente eden bir sınıf.
// Abonelerine mail yolu ile haberleri ulaştırır.

public class MailAboneleri implements Observer {

private Subject haberYayinlayicisi;

public MailAboneleri(Subject haberYayinlayicisi) {
this.haberYayinlayicisi = haberYayinlayicisi;
haberYayinlayicisi.registerObserver(this);
}

public void update(List haberler) {
String mailBody = constructMailBody(haberler);
sendMailToSubscribers(mailBody);
}

/**
* bu metod kayitli tum abonelere mail gonderir.
* Orn: Aboneler veritabanindan cekilebilir.
*/
private void sendMailToSubscribers(String mailBody) {

}

// bu metod gonderilecek mail icerigini olusturur.
private String constructMailBody(List haberler) {

return "";
}

}

// Bu sınıf da Observer interface'ini implemente eden diger siniftir.
// Abonelerine rss kanali ile haberleri ulaştırır.
public class RssAboneleri implements Observer {

private Subject haberYayinlayicisi;

public RssAboneleri(Subject haberYayinlayicisi) {
this.haberYayinlayicisi = haberYayinlayicisi;
haberYayinlayicisi.registerObserver(this);
}

public void update(List haberler) {
String rssXml = constructRssXml(haberler);
putXmlToDirectory(rssXml);
}

// bu metod rss standartlarina uygun xml'i uretir.
private String constructRssXml(List haberler) {
return null;
}

// bu metod uretile xml'i var olan xml dosyasi ile degistirir.
// Aboneler'in kullandiklari rss programlari degisikligi otomatik olarak
// algilarlar...
private void putXmlToDirectory(String rssXml) {

}
}


// Bu sinif da ornek bir calisan sınıftir.
public class Main {

public static void main(String[] args) {
HaberYayinlayicisi haberYayinlayicisi =
new HaberYayinlayicisi();


MailAboneleri mailAboneleri =
new MailAboneleri(haberYayinlayicisi);
RssAboneleri rssAboneleri =
new RssAboneleri(haberYayinlayicisi);

Haber a = new Haber("Olay, olay, olay!!!", "Bina patladi!!!",
"www.habermakinasi.com/?id=5");

Haber b = new Haber("Flas, flas, flas!!!", "Ikinci bina patladi!!!", "www.habermakinasi.com/?id=7");
List haberler = new ArrayList();
haberler.add(a);
haberler.add(b);

haberYayinlayicisi.setYeniHaberler(haberler);
}

}

Kaynak: Head First Design Patterns

21 Mayıs 2007

MyEclipse 5.5 çıktı!!!

Eclipse ortamında uygulama geliştirenler için MyEclipse önemli araçlardan bir tanesi. İçerisinde masaüstünden kurumsal yazılıma kadar çeşitli uygulama alanlarını desteklemektedir. Bu yeni versiyonda Java EE 5'i destekliyor. Bu araç anladığım kadarıyla daha çok Web ve Kurumsal taraftaki geliştirmeye ağırlık vermiş. Örneğin Java ME'yi desteklemiyor gözüküyor özelliklerine bakıldığında.
Özelliklerine şöyle bir baktığımda gözüme çarpanlar EJB 3.0, JPA, sürükle bırak web geliştirme (JSF ile), AJAX, JavaScript debugger, Uygulama Sunucu entegrasyonları, Veritabanı Bağlantı Yöneticisi, Spring desteği idi.
Bundan önce MyEclipse'i bir kere deneme fırsatım olmuştu. O zaman Struts ile web uygulaması geliştiriyorduk. Güzel ve zekice editor'ler sunuyordu o zamanlar. Örneğin struts config dosyasından kaynaklara ve classlara ulaşılabiliyordu, görsel olarak gösterimler de vardı galiba. Bu versiyonda herhalde JSF baya hoş şeyler düşünmüşlerdir, hele hele AJAX desteği de varsa.
İndirip denemek lazım...

20 Mayıs 2007

Modüler JRE

Şurada okuduğum bilgiye göre JRE (Java Runtime Environment) müşteri odaklı, daha basit ve modüler, hale getirilecekmiş. Böylece daha iyi son kullanıcı ve GUI etkileşimleri, ufak dosya indirmeleri, hızlı yüklemeler, hızlı başlangıç gibi son kullanıcıyı memnun edecek özellikler sıralanıyor. Bu özellik Java 6 ile beraber sunulacakmış.
Şu da söyleniyor: Kullanıcı Swing uygulalamalarını çalıştırmak için 3-4 mb'lık JVM'i indirip makinesine kuracak ve uygulama çalışması için ek kütüphaneler istediğinde internetten indirilecekmiş. Ayrıca indirilen yeni paketler diskinizde birden fazla JRE versiyonları oluşturmayacakmış. Buna da on-demand, in-place yükleme demişler.
Bence bu özellik gayet faydalı olur. Çünkü basit bir swing uygulamasını çalıştırmak için 20-30 mb'lık bir JRE yüklemenize gerek kalmaz. Fakat uygulamanın çok fazla ek bağımlılığı varsa bu da çok fazla download'a sebep olacak demektir. Gerçi ilki her zaman kullanışlı olur, ikincisinde gerektiği zaman bir kere indirmiş olacaksınız ve daha sonra indirilen bu kütüphaneleri kullanacaksınız. Gerekmediği zaman niye 20-30 mb'lık bir kurulum kullanayım ki?
Ayrıca indirme olayı benim çalışan programımın çalışmasını etkilememesi lazım. Bu çok önemli bence, aksi takdirde baya eleştiri alır. Örneğin; ben bir uygulamayı çalıştırdım ve uygulama ek bir kütüphaneye ihtiyaç duydu. Kütüphane indirildi ve çalışan uygulama yeniden başlatılmak için sonlandırıldı. Bu göze hoş gözükmüyor. Diyeceksiniz ki indirilecek kütüphane boyutu büyükse uygulama zaten bekleyecek. Zaten indirme hızları git gide artıyor, kaldı ki kütüphane boyutları 50 mb'lık dosyalar değil.
Modüler JRE ile JavaFX (demo) dediğimiz Java'nın son teknolojilerinden birisinin kolay kullanımı hedefleniyor anladığım kadarıyla. JavaFX Adobe Flex'e karşılık geliştirilen bir teknoloji. Daha sonra bu konuya değinmeyi düşünüyorum.
Yalnız Modüler JRE'nin 2008'in ilk yarısı çıkarılmasının düşünülmesi iyi değil zannımca. Çünkü diğerler şirketlerin dereyi geçmiş olmaları muhtemeldir (Flex/Apollo).