Glassfish 3.1.2 Final

Glassfish sunucusunun en son sürümü Glassfish 3.1.2 versiyonu piyasaya sürüldü. Java EE 6’ya tam destek veren Glassfish 3.1.2 versiyonunda yönetici panelinin yavaş açılma sorunu giderilmiş. Eskiye oranla daha hızlı açılıyor.

Bunun yanında yüzlerce bug giderilmiş.

Glassfish hakkında daha fazla bilgi edinmek ve indirmek için aşağıdaki bağlantıya tıklayabilirsiniz :

[box type=”download”] İndir[/box]

Servlet Sınıfları

Servlet sınıfları dinamik web sayfaları tasarlamak için kullanılan nesnelerdir. İlk olarak CGI programlarının dezavantajlarını gidermek için ortaya çıkmıştır. Aslında CGI programlarıyla aynı işi yapsalarda farklı şekilde çalışırlar.

Servlet’ler web container içerisinde ayrı bir process olarak çalışmazlar. Web container kendisi işletim sistemi için bir process’tir. Bu sayede aynı servlet sınıfına birden fazla istek gelse bile birden fazla instance yaratılmaz. Her istek için bir thread oluşturulur.

Avantajları :

  • Java ile yazılmıştır. 🙂
  • CGI’dan çok daha hızlı çalışır.
  • Web container, servlet sınıflarına özel güvenlik ve hata ayıklama servisleri destekler.

Servlet sınıflarının dezavantajı yok denecek kadar azdır. Java ile yazıldığı için bu programlama diline hakim olmak gerekir. Servlet sınıflarının çalışma mantığı şu şekildedir :

  • Servlet’ler, Java sınıfları oldukları için istek geldiği anda instance’larının yaratılması gerekir. Yalnız  normalde biz sınıfların instance’larını new saklı kelimesi ile yaratırken Servlet sınıflarında iş biraz değişir. Web Container başka bir adıyla Servlet Engine, istek sınıfa yapıldığı anda instance yaratır.
  • Servlet sınıflarının diğer sınıflardan farklı olduğu uygulamanın konfigurasyon dosyasında ya da annotation kullanarak belirtilir.
  • Her HTTP metodu için servletlerde kullanılan doXxx() metotları vardır. Gelen isteğin metoduna bakılarak servlet içerisindeki ilgili metot çalıştırılır.

Şimdi en basit haliyle örnek bir servlet kodu yazalım.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author Erkin Pehlivan
 */
@WebServlet(name = "MerhabaServlet", urlPatterns = {"/MerhabaServlet"})
public class MerhabaServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Başlık MerhabaServlet</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Merhaba Dünya</h1>");
            out.println("</body>");
            out.println("</html>");
        } finally {
            out.close();
        }
    }
}

[/codesyntax]

Gördüğünüz gibi bir Java sınıfı içerisinde HTML kodu yazmak zorunda kaldık. Web sayfalarımız daha karmaşık hale geldikçe kod yazmak zorlaşacaktır. İşte JSP sayfalarının çıkışı da buradaki zorluklardan kaynaklanmıştır.

CGI – Common Gateway Interface

Web teknolojisinin çıktığı ilk günden bu yana dinamik sayfalar kullanmak her zaman ihtiyaç olmuştur. Applet’ler bu ihtiyacı karşılamada ilk başlarda kullanılsa da, istemci tarafında çalışmaları bazı sıkıntılara yol açmıştır.

Dinamik içerik üretmek için CGI (Common Gateway Interface) denilen teknoloji yaratılmıştır. CGI’da sunucuya istek (request) gelince küçük bir program çalışır. Sunucuya gelen her istek için bir .exe çalışması gibi düşünün. Bu program kullanılıp işi bittikten sonra hafızadan silindiği için aynı istek tekrar geldiğinde program hafızaya tekrar yüklenip, tekrar çalışır.

Sunucuda birden fazla CGI programı olduğu için, web sunucusunun isteğin hangi programa geldiğine karar vermesi gerekir. Bunu da URL’ye bakarak gerçekleştirir. İlgili CGI programı isteği alır, parse eder, veriyi işler ve geriye cevap döner. Bu cevap genellikle bir HTML sayfası olur.

 

Günümüzde çok fazla olmasa da hala kullanılan bir teknoloji olan CGI’ın avantajları :

–          Başta Perl olmak üzere herhangi bir programlama dili ile yazılabilir, (dezavantaj da olabilir)

–          Çalışmayan ya da bug’ı olan bir CGI programı sunucunun çalışmasını etkilemez,

–          Herbir CGI programı kendi process’ini yarattığı için veri tabanı işlemlerinde eş zamanlı kullanımdan doğan sıkıntılar yaşanmaz,

–          Günümüzde kullanılan çoğu sunucu tarafından desteklenirler.

Bunun yanında dezavantajlarından bahsetmek gerekirse :

–          Her bir CGI programının başlı başına  sunucuda bir process oluşturması sebebiyle cevabı yavaş döndürür,

–          Sunucunun kaynaklarını fazla tüketir,

–          Ölçeklenebilirliği azdır,

–          Bir CGI programı herhangi bir dille yazılabilir. Ancak bu dil her zaman nesneye yönelik ya da güvenilir olmayabilir,

–          Geriye HTML döndürülmesinden dolayı sunucu tarafındaki kodda HTML kullanılması gerekir. Bu da MVC yapısına aykırıdır,

–          Script dilleri genellikle platform bağımlıdır.

Gördüğünüz gibi dezavantajları ağır basan bu teknolojiye alternatif çözümler üretilmiştir. CGI programlarının yaptığı işleri yapan, bunun yanında ekstra özellikleri de olan Java tarafındaki teknolojinin adı da Servlet’lerdir.

MVC – Model View Controller

Veri tabanından sorgulama işlemleri yaparken, yazdığımız ekran kodu içerisine connection alma, sql çalıştırıp dönen sonuçları  görüntüleme kodları yazdığımızı düşünelim.

Daha sonra bir ekrana daha ihtiyacımız olduğunu düşünelim. O ekrandan da veri tabanına bağlanıp dönen sonuçları ekranda görüntüleyeceğiz. Bunu da ekran kodunun içine yazalım. Üçüncü bir ekran yazdık. Bu ekranda da birinci ekrandaki SQL’i kullanan kodu kullanmamız gerekiyor. Aynı kodları bu ekran sınıfına kopyalamamız mümkün ancak SQL’de bir değişiklik yapılması gerektiğinde aynı SQL’i kullanan tüm sınıfların güncellenmesi gerekir. Ayrıca veri tabanı bağlantısı için tüm sınıflarda ayrı ayrı bağlantı açtık, driver’ı register ettik. Veri tabanı bağlantı ayarları değişirse ne olacak? Yine gidip tek tek bütün sınıfları güncellemek gerekecek.

Büyük projelerde değiştirilmesi gereken yer sayısı bir, iki değil birkaç bini buluyor. Bu değişiklikleri yaparken de bazı yerlerin gözden kaçması mümkün ayrıca çok fazla iş yükü oluyor. Ufacık bir değişiklik yapmak için binlerce kopyanın güncellenmesi pek de mantıklı değil. Bir de güncelledikten sonra baktınız hoşunuza gitmedi tekrar birkaç saat uğraşarak eski haline almamız  gerekecek.

Bunun olmaması için bir tane sınıf oluşturuyoruz. Ortak olan tüm kodları buraya yazıyoruz. Mesela veri tabanı bağlantısı için bir sınıf yazıp connection her gerektiğinde bu sınıfı kullanabiliriz. Ya da SQL’ler için bir sınıf yazıp farklı ekranlardan bile olsa aynı SQL çağrılmak istendiğinde bu sınıf kullanılabilir. Böylece unutma şansımız olmuyor ve birden fazla yerde değişiklik yapmaya gerek kalmıyor.

İşte bu şekilde yazılan programlama mantığına çok katmanlı mimari adı veriliyor. Ekranlarımız, SQL’lerimizin olduğu sınıf, bağlantı sınıfı, loglama sınıfı, güvenlik sınıfı gibi birçok katman ortaya çıkıyor. Butona bastığımızda kod sırayla birbirini çağırıyor. Çok katmanlı mimariye uygun bütün projeler bu şekilde yazılıyor. Biz de yazdığımız uygulamanın ilerde gelişeceğine inanıyorsak mutlaka çok katmanlı mimariyi kullanıyoruz.

Katman sayısı yazılımcıya bağlıdır. Ancak en az görsel sayfalarımız, sayfalardan gelen istekleri ele alan kontrol sınıflarımız ve veri tabanı ile ilişkili olan sınıflarımız için 3 katman kullanmak tavsiye ediliyor. Dediğim gibi güvenlik için ayrı bir katman, loglama için ayrı bir katman, filtreler için ayrı bir katman, exception yönetimi için ayrı bir katman daha kullanılabilir. Bu tamamen programcının insiyatifindedir.

Görsel Katman : (View) Son kullanıcıya hizmet veren ekranlarımızın bulunduğu katmandır. Masaüstü uygulamaları için form sınıfları, web uygulamaları için HTML sayfaları, JS dosyaları, resimler vb. bu katmanda yer alır.

Kontrol Katmanı : (Controller) Kullanıcının isteklerini ilgili katmanlara ileten sınıfların bulunduğu katmandır. Örneğin web uygulamalarında yazılan servlet sınıfları bu katmanda yer alır.

Model Katmanı : (Model) Katmanlar arası iletişimi sağlayan bean sınıfları ve diğer tüm işleri yaptığımız iş sınıfları bu katmanda yer alır. Uygulama içerisinde kullanılan Thread sınıfları, veri tabanına istek ve yönlendirme yapan, ayrıca diğer tüm işleri yapan iş sınıfları da yine bu katmandadır.

Logging API

Projelerde loglama hem son kullanıcılar hem de sistem yöneticileri için uygulamanın devamlılığı açısından çok önemlidir. Java’da karşılaşılan güvenlik hataları, konfigürasyon hataları, performans sıkıntıları veya uygulamadaki bug’lar için Logging API kullanılır.

java.util.logging paketinde tanımlanmıştır.

Logging API, bilgileri metin veya XML formatında log kayıtlarını hafızaya, output streamlere, konsola ya da dosyaya yazabilir.

Logging API’yi kullanabilmek için sırasıyla şunlar yapılır :

  1. Logger objesi yaratılır.
  2. Logger objesi konfigure edilir.
  3. Logger objesine mesajlar gönderilir.

Logger objesini yaratmak için java.util.Logger sınıfındaki static getLogger() metodu kullanılır.

Logger logger = Logger.getLogger(“paket.Sinif”);

NOT : Genellikle biricikliği sağlamak için parametre olarak paket ve sınıf ismi verilir. (Tüm sınıf ismi)

Logger objesini konfigure etmek için logger objesine handler tanımlanır. Log seviyesi belirlenir. İsteğe bağlı olarak da filtre tanımlanır.

Logging API’si şu handlerları destekler :

  • StreamHandler (default) : Formatlanmış kayıtları OutputStream objesine yazar.
  • ConsoleHandler : System.err objesine yazar.
  • FileHandler : Bir veya daha fazla dosyaya loglama yapar.
  • SocketHandler : Uzak TCP portlarına loglama yapar.
  • MemoryHandler : Hafızaya logları bufferlar.

Logger’a bir handler eklemek için addHandler() metodu kullanılır. Örnek :

logger.addHandler(new FileHandler(“iko.log”));

Log Seviyeleri:

–          ALL : Tüm mesajlar loglanır.

–          CONFIG : Static konfigurasyon mesajları için kullanılır.

–          FINEST :  Çok fazla detaylı mesajlama için kullanılır.

–          FINER : Daha az ama detaylı mesajlama için kullanılır.

–          FINE : İyi bir mesajlama seviyesidir.

–          INFO : Bilgi mesajlarını loglamak için kullanılır.

–          WARNING : Potansiyel bir problemin ikazlarını loglamak için kullanılır.

–          SEVERE : Çok önemli hataların loglarını yapabilmek için kullanılır.

–          OFF : Loglamayı kapatmak için kullanılır.

Level sınıfından başka sınıflar türeterek kendi seviyemizi yaratabiliriz. Ayrıca setLevel() metodu ile kullanılacak minimum kademeyi seçebiliriz.

Örnek : logger.setLevel(Level.INFO);

Yine aynı şekilde handler objesine de hangi seviyede loglama yapılacağı bilgisini söyleyebiliriz.

Örnek : handler.setLevel(Level.WARNING);

Loglama konfigurasyonu, log için kullanılan ve startup anında okunan konfügurasyon dosyası ile ayarlanabilir. Bu dosya java.util.Properties formatındadır.

 

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.logging;

import java.util.logging.ConsoleHandler;

import java.util.logging.Level;

import java.util.logging.Logger;

/**

 *

 * @author Erkin Pehlivan

 */

public class BasitLoglamaOrnegi {

    public static void main(String[] args) {

        // Logger nesnesi yaratalim

        Logger logger = Logger.getLogger("com.javauzmani.BasitLoglamaOrnegi");

        // konfigure edelim

        logger.addHandler(new ConsoleHandler());

        logger.setLevel(Level.FINE);

        // Farkli seviyelerde log mesajlari

        // loglama icin 7 tane farkli seviye var

        logger.severe("Level:Severe ");

        logger.warning("Level:Warning");

        logger.log(Level.WARNING, "Uyarı mesajı için farklı bir loglama örneği");

        logger.info("Level:info");

        logger.config("Level:configmessage");

        logger.fine("Level:fine");

        logger.log(Level.FINE, "FINE seviyesinde bir loglama örneği");

        logger.finer("Level:finer");

        logger.finest("Level:finest");

    }

}

[/codesyntax]

RMI – Remote Method Invocation

Dağıtık ortamlardaki objeler arası iletişimin gerçekleşmesini sağlar. RMI uygulamalarında socket ve thread yönetimi programcılardan saklanır.

Java RMI farklı sanal makinelerdeki ve farklı host makinelerdeki objeleri çağırmak için kullanılır. Farklı sanal makinelerde yaratılan objelere “remote” objeler denir. Kısaca söylemek gerekirse uzak makinalardaki metodları çağırmak için tasarlanmıştır.

RMI mimarisi 3 bağımsız katmandan oluşur. Bu katmanlar Java uygulaması ile JVM arasında bulunur.

  1. Stub and Skeleton Layer : Bu katman sıralama, network üzerinden gönderilen verinin tekrar orjinal haline dönme işleri, bu verileri alarak Remote Referans Layer’a iletme işlerinden sorumludur. Network üzerinden veri gönderme ve bu verilerin tekrar orjinal haline dönme işleri serialization ile gerçekleştirilir.
  2. Remote Reference Layer : Bu katman isteklerin yürütülme işlerinin gerçekleştirilmesinden sorumludur.
  3. Transport Layer : Bu katman ise bağlantı ayarları, gelen istekleri yönetme, görüntüleme ve gelen istekleri dinleme gibi işlerden sorumludur.

Java RMI 3 ana başlık altında incelenir.

  • Java RMI servers :  Bu sunucu Java RMI arayüzünü implemente eder ve RMI kayıt kütüğüne (registry) nesneyi kaydeder.
  • Java RMI registry : Tüm uzaktaki objeleri izler. Java RMI sunucusunun sunucu sınıfının iskeletine erişmesi gerekir. Uzaktaki objenin iskeleti dediğimiz şey uzak objelerin metodlarına çağrım yapan sunucu taraflı entity’lerdir.
  • Java RMI clients : Önce uzaktaki objelere erişmek için RMI registry’sine bakar. İstemcilerin sunucu sınıfına erişebilmesi gerekir. Bunun için stub adı verilen istemciler için bir proxy vardır. Bu stub uzaktaki objeler için desteklenen tüm arayüzleri implement eder. Stublar ve iskeletler client server arasındaki iletişimi sağlamak amacıyla kullanılırlar.

Java RMI Client, Server ve Registry ilişkilerini gösteren tablo

 

  1. Java RMI sunucu programı, istemci tarafından çağrılacak olan nesnenin instance’ını yaratarak JAVA RMI kayıt kütüğüne (registry) ekler.
  2. Java RMI client programı, registry’ye bakarak uzaktaki objeye erişmek için girişimde bulunur.
  3. Java RMI Registry’si istemciye uzaktaki objenin stub’ının serialize edilmiş halini döner. İstemci de bu nesneyi alır, deserialize eder ve instance’ını yaratır.
  4. Client bu stub’ı kullanarak uzaktaki objenin metodlarından birisini çağırır.
  5. Stub, RMI Server içerisindeki iskelet ile bağlantı kurar.
  6. Bu iskelet istekte bulunulan nesnenin (remote object) metodlarından birisini çağırır.
  7. Cevap iskelete döner.
  8. İskelet cevabı istemciye döndürür.
  9. İstemcideki stub da cevabı alır ve programa iletir.

JAVA RMI UYGULAMASI YARATMAK

  1. Uzaktaki objeyi (remote object) tanımlayan bir arayüz geliştirilir. Bu arayüz (interface) java.rmi.Remote adındaki arayüzden türemelidir.
  2. Bu arayüzü implement eden bir sınıf tasarlanır. (Servent sınıfı)
  3. Servent instancelarını yöneten bir server yaratılır. Yaratılan sunucu aynı zamanda registry’ye kayıt işlemlerinden de sorumludur.
  4. Uzaktaki objeleri kullanan bir istemci yaratılır. İstemcide kayıt kütüğüne sorgu yapılarak alınan nesne üzerinden istenilen metotlara istek gönderilir.

NOT : RMI yardımcı sınıflarını yaratmak için rmic (Java RMI Compiler) çalıştırılır. Java 5’ten sonraki sürümlerle geliştirilmiş uygulamalarda extra rmic çalıştırılmasına ihtiyaç yoktur. Stub sınıfları otomatik olarak  runtime anında yaratılırlar.

Daha detaylı bilgi için tıklayın

SwingX 1.6.3

Java Swing GUI’sine eklentilerle destek veren SwingX’in son sürümü SwingX 1.6.3, 2 Şubat’ta piyasaya çıktı.

Maven’a tam olarak adapte olan kütüphanenin groupId’si org.swinglabs.swingx olarak değişti.

Yeni versiyonda paketler tek bir JAR dosyasında toplanarak güncelleştirildi. Ayrıca  serialization desteği geliştirilerek binlerce bug temizlendi.