Serkan Kaba

Karalama Defteri

JAX-WS ile WsGen kullanmadan web servisi oluşturma

Yazan: Serkan Kaba 10 Haziran 2009

Yakın zamanda farkettiğim bu özellik basit web servislerinin oluşturulmasını ve test edilmesini oldukça kolaylaştırıyor. Araştırdığımda çok daha eskiden beri JAX-WS sürümlerinde var olduğunu öğrendiğim bu özelliği şans eseri 1.6u14 sürümüne girdikten sonra fark ettim. Bu şekilde artık @WebService ile işaretlediğimiz sınıfları Endpoint.publish() ile direk sunabilmekteyiz. Örnek olarak aşağıdaki kodu direkt çalıştırdığımda ws erişilebilir ve kullanılabilir hale gelmekte. Ayrıca çalıştırılırken gerekli sınıfların çalışma anında oluşturulduğuna dair log mesajları oluşturmakta.

package service;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;

@WebService
public class Hello {

	@WebMethod
	public String hello() { return "Hello"; }

	public static void main(String[] args) {
		Endpoint.publish("http://localhost:8080/hello", new Hello());
	}

}

Referanslar

Yazı kategorisi: gezegen, java, yazılım | Leave a Comment »

İzmir’de bir çınar daha devrilmiş

Yazan: Serkan Kaba 26 Mayıs 2009

Gidip de dönmemek dönüp de görememek var. Bu kalıp genelde ayrılıklarda helalleşmek için kullanılır. Ama bazen insan dönüp farklı şeyleri de yerinde bulamaığında da bir garip hüzünle kaplanıyormuş. Evet nerdeyse saat kulesi gibi “Ben bildim bileli orada” bir mekandı “Fil Pizza”. Hayatımda ne pizzasından yedim ne kapısından girdim. Ama o ben bildim bileli (hatta ablam, annem bildi bileli) oradaydı. 13 Mayıs’ta kupa finaline gittiğimde farkettim ki o da kapanmış. Nedeni kriz, ekonomik sebebpler midir bilmiyorum. Ama yıllardır aynı yerde olduğunu bildiğim şeyi görememek bir garip. Neyse umarım diğer semboller bunu yaşamaz (Mesela Sevinç ve Lozan pastaneleri)

Yazı kategorisi: hayat, İzmir | Leave a Comment »

TTNet ve adi(l) kullanım

Yazan: Serkan Kaba 25 Mayıs 2009

8 Mbps’e kadar ADSL paketlerinde, hattın desteklediği hız ile bağlantılı olarak 8 Mbps’e kadar hız sağlanmaktadır. Tüm “8 Mbps’e kadar ADSL paketleri” için aylık 15 GB adil kullanım uygulanacaktır. Aylık download miktarı 15 GB’ı aşması durumunda, ay sonuna kadar download hızı 512 Kbps olarak uygulanacaktır.

Yukarıdaki metin TTNet in sunacağı 8Mbit pkaetleri ile ilgili uyarıdır. Ben de bu paketi duyduğumda aylık az bir ödeme farkıyla bu hizmeti sunacaklar diye sevinmiş hatta geçmeyi de düşünmüştüm. Ancak her zamanki gibi bunun altından tüketiciye bir kazık çıktı. Neymiş evendim “Adil kullanım” mış. Evet ADİ hizmetlerine çok da güzel kılıf uydurmuşlar. Ne diyelim dünyanın en pahalı ve yavaş internet hizmetini almaya devam edeceğiz.

Yazı kategorisi: dumur, gezegen, internet | 8 Yorum »

@Override annotation ve Java5 ile Java6 arasındaki farkı

Yazan: Serkan Kaba 7 Mayıs 2009

Java5 ile gelen annatationlardan biri olan @Override bir metodun eskisini geçersiz kıldığını (override) ifade eder. Ancak Gentoo’da bir hata nedeniyle farkettiğim üzereanlamı Java5 ile Java6 arasında farklılık göstermektedir. Java6′dageçersiz kılınan ve gerçekleştirilen metodlar için @Override kullanılabilirken Java5′te sadece ilk kullanımı geçerlidir. Bu bir hata olarak Sun hata kayıt sistemine defalarca raporlanmıştır. (Benzer ve çift hata kayıtlarından anlaşıldığı üzere) Benim hataların yorumlarından anladığım amacın Java5 için de her iki durumu desteklemek olduğu ancak derleyicideki hata sebebiyle Java5 spesifikasyonunun revize edilerek sadece ilk kullanımın desteklendiği ve Java6′da her iki kullanımım geçerli sayıldığı yönünde. Bunun sebebi ise hatalı da olsa Java5 için uyumluluğu korumak.

Şimdi bu durumu bir örnek üzerinden inceleyelim.

interface Interface {
	public abstract void b();
}

abstract class Base {
	public abstract void a();
}

public class Sub extends Base implements Interface {

	@Override
	public void a() {
	}

	@Override
	public void b() {
	}

}

Bu kod Java6 ile gelen derleyici ile derlenmekte ancak Java5′teikinci @Override için şu hatayı vermektedir.

Sub.java:15: method does not override a method from its superclass
	@Override

İşin ilginç yanı Java6 derleyicisi ile -source 1.5 -target 1.5 parametreleri verildiğinde de hata vermemekte 1.5 ile olan uyumsuzluğu ancak ecj (Eclipse Java derleyicisi) yakalayabilmektedir. Bu sebepten ötürü arayüz metodları gerçekleştirilirken @Override kullanılmaması başka amaçla illa Java6 gerekmiyorsa kodun uyumluluğunu arttıracaktır.

Yazı kategorisi: gentoo, gezegen, java | Leave a Comment »

Generics ve Reflection ile genelleştirilmiş dizi yaratma

Yazan: Serkan Kaba 29 Nisan 2009

Daha önceden buna benzer bir kodu Java 1.4 ile generics kullanmadan yazmıştım. Ancak Generics’in sağladığı özelliklerle tip dönüşümü kodunu metod içine alarak dışarıya tip güvenli bir metod sunabildim. Şimdi örnek kullanım ile metodumuzu görelim.

import java.lang.reflect.Array;

public class GenericArrayDemo {

	public static void main(String[] args) {
		System.out.println(getArray(String.class,10).getClass().getSimpleName());
		String theArray[] = getArray(String.class, 10);
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] getArray(Class<T> clazz,int size) {
		T theArray[] = (T[])Array.newInstance(clazz, size);
		for(int i=0;i<size;i++)
			try {
				theArray[i]=clazz.newInstance();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		return theArray;
	}
}

Burada çıktı olarak String[] üretilmekte ve oluşan dizi direk ve yalnız String dizisine atanabilmektedir. Şimdi örneğimizi genişletelim ve metodun sadece Number sınıfının alt sınıflarını üretebilmesini sağlayalım.

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class GenericArrayDemo {

	public static void main(String[] args) {
		/* Bu satırlar artık Number altsınıfı beklediğimizden hata alacaktır.
		System.out.println(getArray(String.class,10).getClass().getSimpleName());
		String theArray[] = getArray(String.class, 10);
		*/
		System.out.println(getArray(Double.class,10).getClass().getSimpleName());
		Long theArray[] = getArray(Long.class, 10);
		for (Long long1 : theArray) {
			System.out.println(long1);
		}
	}

	@SuppressWarnings("unchecked")
	public static <T extends Number> T[] getArray(Class<T> clazz,int size) {
		T theArray[] = (T[])Array.newInstance(clazz, size);
		for(int i=0;i<size;i++)
			try {
				/* 
				 * Number alt sınıfları parametresiz constructor
				 * içermediği için 0 ile ilklendiriyoruz
				 */
				Constructor<T> constructor=clazz.getConstructor(String.class);
				theArray[i]=constructor.newInstance("0");
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		return theArray;
	}
}

Bu metod ise Double[] ve ardından 10 adet sıfır yazdırmaktadır. Artık Number alt sınıfı beklediğinden bir önceki örnekteki satırlar çalışmamaktadır. Burada sınıfa ait String parametresi alan Constructor üretilmekte ve o şekilde ilklenmektedir.

Bunu benim kullanım amacım veritabanında çağırılan stored procedure sonuçlarını uyumlu bir sınıf dizisine eşleyebilen genel bir metod yazmak idi. Belki daha farklı kullanım amaçları da olabilir.

Yazı kategorisi: gezegen, java | Leave a Comment »

Geocities kapılarını kapatıyor

Yazan: Serkan Kaba 24 Nisan 2009

Uzun zamandan beri Türkiye’de mahkeme kararıyla kapalı olan Geocities hizmeti yahu tarafından durduruluyor. Yeni kullanıcı kayıtlarına kapatılan site yıl içinde tamamen kapanacak. 90′ların sonunda oldukça moda olan ve zamanının ötesindeki online editörüyle benim gibi pek çok insanı “1-2 tıkta” web sitesi sahibi eden Geocities de Yahoo Briefcase ile aynı kaderi paylaşıyor. O zamanlar için “aşmış” sayılabilecek bu iki hizmet de malesef zamana yenik düştü ve değerini yitirdi.

Güle güle Geocities!

Yazı kategorisi: gezegen, internet, yahoo | 1 Yorum »

AmaterasUML: Açık kaynak ve uyumluluk üzerine bir hikaye

Yazan: Serkan Kaba 20 Nisan 2009

Bytecode uyumluluğu ve API uyumluluğu

Java kodlarımızı derlerken derleyiciye -source ve -target parametrelerini vererek belli bir sürüme ait bytecode a derleyebiliyoruz. Tabi burada yeni sürüme ait DİL özelliklerinden feragat ediyoruz. Örnek olarak kodumuzu Java 1.4 için derlemek istersek Generics, Boxing gibi özellikleri kullanamayız. Ancak bu işlem aynı garantiyi JDK’nın sunduğu API için sağlamamaktadır. Örnek olarak Java6 ile yeni gelen bir sınıfı kullanıp Java5 ile çalıştırdığımızda ClassNotFoundException, Java6 ile yeni gelen metodu Java5 ile çalıştırdığımızda NoSuchMethodError hatası alırız. Bu durumda en emin yöntem geliştirirken hedef aldığımız minimum majör sürümü (Örn: Java5) kullanmamız olacaktır. Artık pek çok IDE proje bazında  kullanılan JRE/JDK sürümünü seçmemize izin vermektedir.

AmaterasUML Eclipse eklentisini Java5 ile çalıştıtırken aldığım hata

Gelelim hikayemizin gelişme bölümüne. Eclipse için geliştirilmiş açık kaynaklı bir UML eklentisi olan AmaterasUML tam olarak da bu sorundan müzdarip. Eklenti ikili dosyaları Java5 sisteminde çalışmasına rağmen UML oluşturması için sınıfları ekrana sürüklediğimizde java.lang.NoSuchMethodError: java.util.Arrays.copyOf([Ljava/lang/Object;I)[Ljava/lang/Object; hatası alıyoruz. Bunun sebebi ise Arrays.copyOf() metodunun Java6 ile yeni gelmiş olması.

Nasıl düzelttim?

Gelelim çözüme. Şanslıyız ki eklentimiz açık kaynak kodlu. Aslında bahsetmedim ama sorunun kaynağını bulabilmek için de projenin kaynak kodunu inceledim. Şimdi tek kalan şey bunu düzeltmek, test etmek ve geliştiriciye yollamak. Bunun için Proje kodunu SVN’den indirip açtım ve JDK 1.0′dan beri varolan System.arraycopy() metodunu kullandım. Daha sonra düzenlenmiş kod ile eklenti dosyasını yeniden oluşturup kendi oluşturduğum dosyadan kurdum. Ve, evet eklenti olması gerektiği gibi çalıştı ve sınıflarda UML diyagramı oluşturdu. Ardından yamayı oluşturarak projenin ulaştığım iki sitede (Sourceforge ve Java.net) yer alan hata kayıt sistemlerine bildirdim.

Hata Kayıtları

Yazı kategorisi: eclipse, gezegen, java | Leave a Comment »

Evince ile özgür PDFler

Yazan: Serkan Kaba 17 Nisan 2009

Geçenlerde elime yazdırma korumalı bir PDF geçti. O an elimde sadece Acrobat Reader olduğu için yazdırma imkanım olmadı. Ancak GNOME masaüstünde kullandığım Evince’in bunu bir şekilde aşabileceği düşüncesi oluştu. Ne de olsa ekrana gösteriyorsa yazdırabilirdi de. Evince kaynak kodunu incelerken bunun /apps/evince/override_restrictions anahtarıyla kontrol edildiğini farkettim. Üstüne üstük bu anahtarın varsayılan değeri true idi. Bunun düşünülmüş olmasına şaşırmadan PDFyi açtım ve dosyaya yazdır seçeneği ile yeniden kısıtsız PDF olarak oluşturdum. Bu adımdan sonra oluşan PDFyi Acrobat Reader ile yazdırabildim. Eğer bu ayar dağıtımınızda varsayılan olarak true değilse ekrandaki gibi değiştirebilirsiniz.gconf3

Yazı kategorisi: gezegen, linux, pdf | 2 Yorum »

Yeditepe Üniversitesi seminerinin ardından

Yazan: Serkan Kaba 17 Nisan 2009

Yeditepe Üniversitesi’n'de verdiğim “Açık Kaynak Kodlu Yazılım Geliştirme” semineri benim için bir ilkti. Daha önceden bu tarz bir seminer hiç vermemiştim. Ancak kendi adıma iyi geçtiğini düşünüyorum. İyi bir başlangıç iyi bir tecrübe oldu. Çok kalabalık bir grup olmasa da az sayıda insana da bilgi verebilmiş, açık kaynak kodlu projelere katılmayla ilgili heveslendirebildiysem ne mutlu bana. Buradan gayreti için Yeditepe Üniversitesi Bilgisayar Topluluğu başkanı Zafer ÇAKMAK’a teşekkür etmek isterim.

Şimdi darısı önümüzdekinin belki de yenilerinin başına.

Not: Seminer sunumuna yeni açtığım Verdiğim Seminerler sayfasından erişilebilir.

Yazı kategorisi: gezegen, linux, seminer, yazılım | 1 Yorum »

Singleton Pattern üzerine

Yazan: Serkan Kaba 16 Nisan 2009

Singleton pattern kullanım amacı bir sınıfın kısıtlı nesnesini (hatta çoğunlukla tek) tek bir yerden yaratılması amacıyla kullanılmaktadır.  Şimdi bunu sağlayan Singleton sınıfı kodunu görelim. (Kod 1)

public class Singleton {
	private static Singleton theInstance = new Singleton();
	// Sınıf yüklendiğinde yaratılan tekil nesne

	public static Singleton getInstance() {
		// Dışarıdan nesne almak için bu metodu kullanacağız.
		return theInstance;
	}

	private Singleton() {
		// Constructor private tanımlansın ki dışarıdan erişilemesin.
		System.out.println("constructor");

		//Constructor 100 ms. bekleme gibi bir "iş" yapsın.
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Burada sınıfın nesnesine sadece getInstance() metodu ile erişilebilecektir. Ccnstructor 100 ms. gibi “makul” bir süre beklemektedir. Bu sınıftan nesneleri yaratan sınıfımızın kodunu da inceleyelim. (Kod 2)

public class SingletonTest {

	private static Singleton singletona, singletonb;

	public static void main(String[] args) {
		singletona = Singleton.getInstance();
		singletonb = Singleton.getInstance();
		System.out.println(singletona == singletonb);
	}

}

SingletonTest sınıfını çalıştırdığımızda aşağıdaki gibi bir çıktı vermektedir.

constructor
true

Görüldüğü üzere kodumuz amacına ulaşmış constructor 1 defa çağırılmıştır. Ancak bu yöntemde Singleton sınıfının nesnesi sınıf yüklendiği anda ilklenmektedir. Şimdi bu ilklemeyi ihtiyaç anına bırakalım (Lazy initilization). Yeni Singleton sınıfımız şu şekilde oluşacaktır. (Kod 3)

public class Singleton {
	private static Singleton theInstance;
	// İhtiyaç anında yaratılacak nesne

	public static Singleton getInstance() {
		// Dışarıdan nesne almak için bu metodu kullanacağız.
		// Eğer nesnemiz yaratılmamış ise yaratalım.
		if (theInstance == null) {
			theInstance = new Singleton();
		}
		// Şu an ya da önceden yaratılan nesneyi döndürelim.
		return theInstance;
	}

	private Singleton() {
		// Constructor private tanımlansın ki dışarıdan erişilemesin.
		System.out.println("constructor");

		// Constructor 100 ms. bekleme gibi bir "iş" yapsın.
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Bu şekilde de programımızı çalıştırdığımızda aynı çıktıyı vermekte ve beklenen şekilde işlemektedir. Şimdi SingletonTest sınıfını biraz değiştirelim ve getInstance() birden çok threadden çağırıldığında ne yapıyor onu görelim. (Kod 4)

public class SingletonTest {

	private static Singleton singletona, singletonb;

	public static void main(String[] args) {
		// getInstance() iki ayrı thread ile çağırılsın.
		Thread threada = new Thread() {

			@Override
			public void run() {
				singletona = Singleton.getInstance();
			}

		};
		threada.start();

		Thread threadb = new Thread() {

			@Override
			public void run() {
				singletonb = Singleton.getInstance();
			}

		};
		threadb.start();

		// Her iki thread tamamlanana kadar beklensin
		while (!(threada.getState() == Thread.State.TERMINATED && threadb
				.getState() == Thread.State.TERMINATED))
			;

		System.out.println(singletona == singletonb);
	}

}

Çıktımıza göre buu sefer sapıttı sanırım.

constructor
constructor
false

Evet constructor iki defa işledi ve bize iki ayrı nesne üretti. Şimdi ilklendirmemizi thread-safe hale getirelim. Bunu da getInstance() metodunu synchronized olarak tanımlayarak yapacağız. (Kod 5)

public class Singleton {
	private static Singleton theInstance;
	// İhtiyaç anında yaratılacak nesne

	public static synchronized Singleton getInstance() {
		// Dışarıdan nesne almak için bu metodu kullanacağız.
		// Eğer nesnemiz yaratılmamış ise yaratalım.
		// Metodu synchronized yaparak sayesinde aynı anda sadece bir yerden
		// çağırılmasını garanti ettik.
		if (theInstance == null) {
			theInstance = new Singleton();
		}
		// Şu an ya da önceden yaratılan nesneyi döndürelim.
		return theInstance;
	}

	private Singleton() {
		// Constructor private tanımlansın ki dışarıdan erişilemesin.
		System.out.println("constructor");

		// Constructor 100 ms. bekleme gibi bir "iş" yapsın.
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Evet! Eski çıktımıza geri döndük. Ancak unutmayalım ki synchronized Java’nın bize sağladığı bir imkan onun için Wikipedia Singleton pattern başlığında gördüğüm yöntemle devam edeceğiz. Bu yöntemde ilk koddaki gibi ilkleme sınıf yükleme esnasında ancak yardımcı başka bir sınıfın yüklenmesinde gerçekleşecek. (Kod 6)

public class Singleton {
	private static class SingletonHolder {
		// İlklemeyi ilk örnekteki gibi sınıf yüklemesi esnasına taşıyacağız.
		// Ancak bu sefer ilklemeyi Singleton değil yardımcı başka bir sınıf
		// gerçekleştirecek.
		private final static Singleton INSTANCE = new Singleton();
	}

	public static Singleton getInstance() {
		// Bu kullanım SingletonHolder sınıfının yüklenmesini dolayısıyla
		// Singleton nesnesinin ilklenmesini tetikleyecek.
		return SingletonHolder.INSTANCE;
	}

	private Singleton() {
		// Constructor private tanımlansın ki dışarıdan erişilemesin.
		System.out.println("constructor");

		// Constructor 100 ms. bekleme gibi bir "iş" yapsın.
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Yazı kategorisi: gezegen, java, linux, yazılım | 5 Yorum »