Swing exceptionlarını yakalamak.

28 June, 2009 (04:04) | Programming | By: selcuk

Swing EDT (Event dispatch thread) threadi içerisinde bir exception çıktığında bu exceptionı kendi threadinizde yakalamanız mümkün olmaz.

Exceptionlar stack ile alakalı olduklarından fırlatıldıklarında kendi stacklerinde handle edilebilirler.

EDT Nedir ?

Swing ve AWT nin kendi eventlerini, boyama işlerini yönettiği bir thread vardır. Bu threade Event dispatch thread (EDT) olarak isimlendirilmiştir.

Swing libraryden herhanbir class kullanıldığında mutlaka bu thread içerisinde oluşturmak ve kullanmak gerekmektedir. Main threadden EDT içerisine girmek için bir kaç yol var, fakat en çok tercih edileni, SwingUtilities.invokeLater metodudur.  Daha yeni ve daha yakışıklı bir metod daha incelenmek istenirse, JSR 296: Swing Application Framework specinde tanıtılmıştır. Fakat EDT exception konusunu tamamlamak için biz şimdilik SwingUtilities.invokeLater kullanmaya devam edelim.

public static void main(String[] args) {

	SwingUtilities.invokeLater(new Runnable() {
	    @Override
	    public void run() {
		/*
		 * Devam eden satirlar EDT içerisinde çalışmaktadır.
		 */
		JFrame frame = new JFrame("Pencere başlığı");
		frame.setSize(new Dimension(320, 240));
		frame.setVisible(true);
		throw new RuntimeException("EDT içerisinde bir exception fırlatıldı.");
	    }
	});

}

Yukarıdaki örneğimizde JFrame’, event dispatch thread içerisinde kullanmış olduk.

Bu thread içerisinde bir runtime exception fırlatıldığında bunu yakalayıp kullanıcıya göstermek istersek nasil bir yöntem izleyebiliriz.

Benzer şekilde JSR296 ile tanıtılan SwingWorker lar içerisinde de runtime exceptionlar fırlatılmış olabilir. Bunları da yakalayıp kullanıcıy bilgilendirmek isteyebiliriz.

Dolayısıyla bizim ihtiyacımız olan şey, deyim yerinde ise threadler üstü bir exception yakalama mekanizmasıdır.

Thread.setDefaultUncaughtExceptionHandler

Thread sınıfının static bir metodu “setDefaultUncaughtExceptionHandler”,  zaten isminden de anlaşılacağı gibi, tüm threadlerde herhangibir catch bloğunda yakalanarak yutulmayan exceptionların handle edilmesini sağlıyor. Bunun için Thread.UncaughtExceptionHandler interface inin bir implemantasyonunu motoda geçmeniz gerekir.

Anonymous bir şekinde implement ederek tanıtacak olursak kodumuz aşağıdaki gibi olacaktır.

import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class AppClient {

    public static void main(String[] args) {

	Thread
		.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
		    public void uncaughtException(Thread t, final Throwable e) {
			SwingUtilities.invokeLater(new Runnable() {
			    @Override
			    public void run() {
				/*
				 * JOptionPane bir swing sınıfı olduğundan,
				 * SwingUtilities.invokeLater ile kullanılıyor.
				 */
				JOptionPane.showMessageDialog(null, e
					.getMessage());
			    }
			});
		    }
		});

	SwingUtilities.invokeLater(new Runnable() {
	    @Override
	    public void run() {
		/*
		 * Devam eden satirlar EDT içerisinde çalışmaktadır.
		 */
		JFrame frame = new JFrame("Pencere başlığı");
		frame.setSize(new Dimension(320, 240));
		frame.setVisible(true);
		throw new RuntimeException(
			"EDT içerisinde bir exception fırlatıldı.");
	    }
	});
    }
}

Artık ister EDT ister Swingworkerlar içerisinde olsun, herhanbiri exception yakalanmadığı takdirde mutlaka tanıtmış olduğumuz Thread.UncaughtExceptionHandler tarafından handle edilmiş olacaktır.

Son olarak delphicilere bir not, bu şekilde global exception handler tanıtmış olduk. Delphi deki default exception handler mekanizması ile aynı sonucu elde etmiş oluruz. Delphi de siz hiç bir şey yapmasanız da bir exception oluştuğunda mutlaka ekranda bir messagebox ile gösterililir. Bu şekilde Java Swing uygulamasında da benzer bir davranışı elde etmiş olduk.

Kolay gelsin.

Write a comment