Arşiv

‘Java’ kategorisi için arşiv

Refactoring

Pazar, 23 Şub 2014 3 yorum

Büyük oranda Martin Fowler’ın “Refactoring – Improving The Design of Existin Code” kitabından faydalandığım Refactoring eğitiminin sunumunu paylaşayım dedim, bir faydası dokunması umuduyla.

Martin Fowler‘ın tanımıyla Refactoring yazılımın gözlemlenen davranışlarını değiştirmeyen, fakat iç yapısını değiştiren bir dizi küçük iyileştirmedir.

Sunum kabaca şu başlıklardan oluşuyor;

  • Refactoring Nedir ?
  • Neden Refactor Etmek Gerek ?
  • Ne Zaman Refactor Etmek Gerek ?
  • Nasıl Refactor Etmek Gerek ?
  • Refactoring Kataloğu

Not : “Refactoring”, “refactor etmek” gibi tabir ve terimlere Türkçe’de getireceğim karşılıklar kulak tırmayalayabileceği için oldukları gibi kullanmak durumunda kaldım.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Google Guava – EventBus (Observer Pattern Uygulaması)

Cumartesi, 25 May 2013 Yorum yapılmamış

Google’ın faydalı kütüphanesi Guava‘da geniş kullanıma müsait, esnek ve sade bir observer pattern uygulaması mevcut; EventBus. Sağladığı diğer bazı avantajlarla beraber düşününce birden observer pattern ihtiyacı olan her duruma uygulanabilir geldi gözüme. Bir nevi “silver bullet” gibi. Elbette ki değil, yok öyle bir şey.

EventBus sınıfı observer pattern‘deki olay yayınlayıcısı sınıfa (publisher) karşılık geliyor. EventBus’ın yayınlayacağı olaylardan haberdar olmak isteyen sınıflar (subscriber) bu sınıfa kayıt oluyorlar. Kayıt olmuş bu sınıflar EventBus bir olay yayınladığında @Subscribe ile belirtilmiş, tek parametresi yayınlanan olayın tipinde bir parametre olan metotları ile bu olayı yakalayabiliyorlar. EventBus haber vereceği metodu/metotları bulurken sınıf hiyerarşisini dikkate alıyor. Bu durum çok biçimliliğe elverişli, esnek kod yazabilmek açısından oldukça kullanışlı.

Bir örnek üzerinden anlatacak olursam; PolitikaHaberi, SporHaberi, HavaDurumuHaberi tipinde ve her biri Haber‘den türemiş sınıflar olsun. @Subscribe ile bildirilmiş ve tek parametresi PolitikaHaberi olan bir metot PolitikaHaberi türünde haberleri dinleyebilir. Genel bir ihtiyaç durumunda her türlü haber dinlenmek isteniyorsa mesela, bu iş @Subscribe ile bildirilmiş ve tek parametresi Haber olan bir metot ile yapılabilir.

...
@Subscribe
public void listenToSportsNews(SportsNews sportsNews){
	System.out.println("Hearing from..." + sportsNews.getType());
	for(String news : sportsNews.getNews()){
		System.out.println(news);
	}
		
}
...

@Subscribe
public void listenToNews(News newsNewsNews){
	System.out.println("Hearing from any type of news. This time : " + newsNewsNews.getType());
	for(String news : newsNewsNews.getNews()){
		System.out.println(news);
	}
	
}
...
...
//Create newsEventBus object
		EventBus newsEventBus = new EventBus("News from Earth !");;
		
		//Create newsBulletin
		NewsBulletin newsBulletin = new NewsBulletin();
		
		//Create newsListener, and register to the newsEventBus (start listening to)
		NewsListener newsListener = new NewsListener();
		newsEventBus.register(newsListener);
		
		//Publish news
		newsEventBus.post(newsBulletin.publishPoliticsNews());
		newsEventBus.post(newsBulletin.publishSportsNews());
		newsEventBus.post(newsBulletin.publishWeatherNews());
		
		//Unregister from the newsEventBus (stop listening to)
		newsEventBus.unregister(newsListener);		
...

Burada bilinmesi gerek yukarıda da söylediğim gibi EventBus bir olay yayınladığında çağıracağı metotları sınıf hiyerarşisini dikkate alarak buluyor. Bu yüzden SporHaberi yayınlandığında bunu hem spor haberi dinleyen hem de haber dinleyenler duymuş oluyor. Daha veciz bir ifadeyle Haber dinleyen her türlü haberi, SporHaberi dinleyen yalnızca spor haberini duyuyor.

EventBus sınıfı uygulamanın ihtiyacına bağlı olarak bir kere/tane (singleton) veya birden fazla oluşturulabiliyor. Farklı bağlamları olan her bir olay grubu için bir EventBus tanımı yapılabilir pekala. Daha fazla uzatmadan kaynakları işaret ederek bitireyim. Google Guava kütüphanesine şuradan erişilebilir. Detaylı bilgi ve açıklama için Google geliştirici sayfası da şurada. Eli yüzü daha düzgün bir örnek uygulama da burada

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Hibernate Blob Tipi – Criteria API Example uyuşmazlığı

Pazartesi, 10 Ara 2012 Yorum yapılmamış

Geçenlerde epeyce vaktimi alan bir hatayı nasıl çözdüğümüzden bahsedeyim. Olur da benzer bir hata ile cebelleşen birileri arar da denk gelir. Üşenme yaz, kullanıcı bilmezse Google bilir.

Bütün mesele bir dosyayı veritabanında BLOB olarak tanımlanmış bir kolona yazmaktı aslında. Dosya içeriğini byte[] tipinde değil de, java.sql.Blob tipinde tanımlamak gerektiğini öğrendim bu arada, aksi durumda eşlemede tip uyuşmazlığı hatası alınıyor.

Entity sınıfı : File.java

...
private Blob fileContent;
//private byte[] fileContent; 
...

Hibernate eşleme(mapping) dosyası : File.cfg.xml

...
<property name="fileContent" type="blob" column="FILE_CONTENT" />
...

(Hibernate Annotation ile aynı hata oluşuyor mu bilmiyorum bu arada)

şeklinde eşledim dosyanın içeriğini. Fakat testleri çalıştırdığımda

java.sql.SQLSyntaxErrorException: ORA-00932:
inconsistent datatypes: expected – got BLOB

şeklinde bir hata ile karşılaştım. Uzunca bir süre debelendikten sonra, basit bir hibernate projesi oluşturup, önce en güncel hibernate kütüphaneleri ile sonra da 3.6 sürümü kütüphaneleri ile test ettim. Herhangi bir sorun olmadan yukarıdaki eşlemelerle dosyayı kaydedebildim. Forumlarda benzer bir sorunla karşılaşmış olanların belirttiği hibernate.cfg.xml‘de çeşitli ayar değişiklikleri yapmak, hibernate ve bağımlı olduğu kütüphanelerin sürümlerini incelemek, debug loglarını satır satır incelemek ve sair derken uzunca bir maratondan sonra oyunun sonunu getirdik, prensesi kurtardık.

Sorunun kaynağı Blob tipi bir alana sahip sınıf için Hibernate Criteria API’nin Example yapısı ile arama yapmak imiş. Böyle bir durumda yukarıdaki gibi bir tip uyuşmazlığı hatası alınıyor. Çözüm olarak ilk akla gelen Blob tipindeki alanı excludeProperty olarak belirtip, kriter listesinin dışında bırakmaktı tabi ki.

...
File file = new File();
file.setName("XFile");
...
//set other file properties
...
//Create an example to search for
Example example = Example.create(file)
//but exclude the property named "fileContent"
                  .excludeProperty("fileContent");  

List<File> results = session.createCriteria(File.class).add(example).list();
...

Muhtemelen benzer hatayı Clob tipi için de verecektir. Akıllarda buluna, gaflete düşülmeye…

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Java Enum Reverse Lookup

Perşembe, 17 May 2012 Yorum yapılmamış

Java 1.5 sürümü ile birlikte gelen Enum sınıfı genel itibariyle sabit verileri tanımlamak için kullanılır. 1.5 öncesi static final olarak tanımlanan sabit verilere denk gelir bir nevi. Çoğu zaman da bu sabit verilerle ilişkilendirilmiş bir kod eşlemesi yapılır. Döviz-döviz kodu, elemen-element simgesi, durum-durum kodu gibi…Bu kod tanımı Enum sınıfın yapılandırıcısına parametre geçilerek yapılır.

public enum Gender {
	Male("M"),
	Female("F");

	private String code;

	private Gender(String code) {
		this.code = code;
	}

	public String getCode() {
		return code;
	}
}

Herhangi bir enum değerin code alanına

Gender.Male.getCode()

şeklinde erişebiliriz.

Bahsetmek istediğim ise bunun tam tersi durumda yani code alanından enum değere erişmek istediğimiz durumda ne yapılabileceği. Bu durumun tam karşılığı “enum reverse lookup”.

public enum Month {
	JAN(1),FEB(2),MAR(3),APRIL(4),MAY(5),JUN(6),JUL(7),AUG(8),SEP(9),OCT(10),NOV(11),DEC(12);
	private int code;

	private Month(int code) {
		this.code = code;
	}

	public int getCode() {
		return code;
	}

}

şeklinde bir enum sınıfı olduğunu varsayarsak code alanından Month enum değerine

public Month getMonthFromCode(int code){
  for (Month month : Month.values()){
	  if (month.getCode() == code)
		  return month;
  }
  return null;

şeklinde erişilebilir.

Fakat her seferinde bir for döngüsü ile enum değerleri içinde dönmek yerine static bir Map tanımlayıp, bütün enum değeri-kod eşleşmeleri bu Map‘e koyularak, istenen enum değere her seferinde tek hamlede de erişlebilir. Şöyle ki;

public enum Month {

JANARY(1),FEBRUARY(2),MARCH(3),APRIL(4),MAY(5),JUNE(6),JULY(7),AUGUST(8),SEPTEMBER(9),OCTOBER(10),NOVEMBER(11),DECEMBER(12);
	private int code;

	private static Map enumCodeMap;
	static {
		enumCodeMap = new HashMap();
		for(Month month : Month.values()){
			enumCodeMap.put(month.getCode(), month);
		}
	}

	public static Month getMonthFromCode(int code){
		return enumCodeMap.get(code);
	}

	private Month(int code) {
		this.code = code;
	}

	public int getCode() {
		return code;
	}

}

şeklindeki bir enum tanımı sonrası

Month month = Month.getMonthFromCode(6);
//JUNE

denilebilir. Bu şekilde static bir tanım ile JVM, Month enum sınıfını yüklediğinde hazır hale gelmiş olan enumCodeMap değişkeni üzerinden her seferinde teknik olarak da, kod satırı olarak da tek hamle ile istenen enum değere erişilmiş olur.

Düzenleme : Bu durumla tam olarak örtüşen bir örnek, periyodik cetveldeki elementlerin tutulduğu bir enum sınıfı olabilir. Element adı enum değeri, element simgesi kod olacak şekilde oluşturulmuş olan bir Element enum sınıfı düşünülebilir. Altın’ın simgesi olan “Au” ya erişmekten ziyade, simgesi “Au” olan elemente erişmek lazım olduğu durumlarda bu yöntem kullanılabilir

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail
Kategoriler:Java Etiketler:, , ,

Java’da TimeUnit Kullanımı

Pazartesi, 23 Nis 2012 1 yorum

Yeni farkına varıyorum ki meğer Java’nın 1.5 ile beraber gelmiş TimeUnit diye bir enum sınıfı varmış. Şu can sıkıcı, her seferinde tekrar tekrar yapmak zorunda kalabildiğimiz zaman dönüşümü işlerini üstlenmiş. Gün, saat, dakika, saniye, milisaniye ve nanosaniye cinsinden zaman birimlerini birbirine dönüştürüveriyor.

Şöyle ki;

package com.selman;

import java.util.concurrent.TimeUnit;

public class TimeUnitTests {
	public static void main(String[] args) throws InterruptedException {
		long baslangic = System.currentTimeMillis();
		Thread.sleep(1300);
		long bitis = System.currentTimeMillis();
		
		//baslangic ile bitis arasindan gecen zamanin milisaniye cinsinden degeri 
		System.out.println(TimeUnit.MILLISECONDS.toMillis(bitis) - TimeUnit.MILLISECONDS.toMillis(baslangic) + " ms");
		//baslangic ile bitis arasindan gecen zamanin saniye cinsinden degeri 
		System.out.println(TimeUnit.MILLISECONDS.toSeconds(bitis) - TimeUnit.MILLISECONDS.toSeconds(baslangic) + " sn");
		
		
		//48 saatin gun cinsinden degeri 
		System.out.println(TimeUnit.DAYS.convert(48, TimeUnit.HOURS) + " gun");

		//10 gunun saat cinsinden degeri 
		System.out.println(TimeUnit.HOURS.convert(10, TimeUnit.DAYS) + " saat");
		
		//3656 saniyenin dakika cinsinden degeri
		System.out.println(TimeUnit.MINUTES.convert(3656, TimeUnit.SECONDS) + " dakika");
	}
}
/*--------*/
//1297 ms
//1 sn
//2 gun
//240 saat
//60 dakika

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Java ile IMDB’den film bilgisi almak

Çarşamba, 09 Kas 2011 Yorum yapılmamış

Her şey harici diskte yer açmaya çalışmakla başladı : ) Önceleri adından gözüme kestirdiğim, şöyle basmakalıp Hollywood aksiyon veya romantik komedi türü filmleri imdb’de bir göz attıktan sonra siliyordum. Sonraları bu iş can sıkıcı olmaya başladı. Yok mudur bunun bir API’si, topluca bulayım bu filmleri de külliyen uçurayım kellerini falan diye bakmaya başladım. Nihayetinde eli yüzü düzgün, inciği boncuğu olmayan bir servis buldum. Şurada sunulan servis ile ilgili linke film adı ve/veya yılını parametre olarak geçtiğinizde film bilgileri json formatında bir nesne olarak dönüyor. Geriye json formatındaki bu nesneyi ayrıştırmak kalıyor. Bunun için de halihazırda API’ler mevcut.

Şöyle ki;

package com.imdbInfo.base;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

public class BasicTest {


private static final String BASIC_API_URL = "http://www.imdbapi.com/?";
private static final String TITLE_PARAM = "t=";
@SuppressWarnings("unused")
private static final String YEAR_PARAM = "&amp;amp;y=";

public static void main(String[] args) {


try {

String titleToSearch = URLEncoder.encode("Forrest Gump","UTF-8");

String text = getJSONStringOf(BASIC_API_URL + TITLE_PARAM + titleToSearch);

JSONObject jSonObject = (JSONObject) JSONSerializer.toJSON(text);

String title = jSonObject.getString("Title");
int year = jSonObject.getInt("Year");
int votes = jSonObject.getInt("Votes");
double rating = jSonObject.getDouble("Rating");
String genre = jSonObject.getString("Genre");
//Runtime, Director vs.
System.out.println("Title:" + title + "\nYear:" + year + "\nVotes:" + votes + "\nRating:" + rating + "\nGenre:" + genre);

}
catch (Exception e) {

//Movie not found !
e.printStackTrace();

}

}

public static String getJSONStringOf(String urlSpec) throws Exception {

URL url = new URL(urlSpec);
URLConnection connection = url.openConnection();

BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line = "";
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null) {

builder.append(line);

}

return builder.toString();

}

}

Title:Forrest Gump
Year:1994
Votes:325985
Rating:8.6
Genre:Drama, Romance

diyerek filmin bilgilerini almış oluyoruz. Bunların içinde film adı, yapım yılı, türü, kullanılan oy sayısı, puan, yönetmen, oyuncular, süre ve sair filmle ilgili bir sürü bilgi bulunuyor.

Bundan sonra eldeki filmleri bu servisten alınan bilgiye göre sınıflandırmak kalıyor. Ki işin keyifli kısmı da orası : ) Yalnız şunu belirtmemde fayda var. Bu servisin elindeki veri imdb’nin yayınlamış olduğu film veritabanından alınıyor. Sanırım biraz eski. Araştırmadım ama tahminimce bir kaç ay kadar. Ziyanı yok : )

Kodu bu haliyle kullanabilmek için projenin ‘classpath’ inde commons-beanutils,commons-collections-3.2.1, commons-lang, commons-logging, ezmorph-1.0.5 ve json-lib-2.4-jdk15 jar’larının bulunması gerekliyor.

Daha bir eli yüzü düzgün ve gerekli jar’ları barındıran kod örneği şuradan indirilip incelenebilir, Eclipse’e import edilebilir.

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail

Java’da listeleri generic olarak gruplamak

Cuma, 07 Eki 2011 Yorum yapılmamış

Kod yazarken bir listenin elemanlarını belirli bir alana göre gruplamak sıkça yapılan işlerden biridir. Personelleri işe giriş tarihine göre veya arabaları modelinin tipine göre gruplamak gibi. Gruplanan bu veriler de genel olarak Map türü bir veri yapısında tutulur. Bu işi genel(generic) olarak yapabilen ve gruplamaya kriter olan alanın seçiminde aşağı doğru dallanabilen bir metot kod tekrarını oldukça azaltması açısından faydalı olabilir. Sırf ben biliyorum çalıştığım projede bu işi kaç kere yaptığımı : )

Bu kodu kullanabilmek için classpath’e commons-beanutils.jar ve commons-logging.jar’ı eklemek gerekiyor.

Ayrıca eclipse projesi şuradan indirilip incelenebilir, import edilebilir.

public static <E, T> Map<E, List<T>> group(List<T> listToGroup, String groupingCriteria) {

Map<E, List<T>> grupMap = new HashMap<E, List<T>>();
for (T item : listToGroup) {
try {
E e = (E) BeanUtils.getProperty(item, groupingCriteria);
if (grupMap.containsKey(e)) {
grupMap.get(e).add(item);
} else {
List<T> list = new ArrayList<T>();
list.add(item);
grupMap.put(e, list);
}
} catch (IllegalAccessException exception) {
throw new RuntimeException(“Error in grouping !” + exception.getMessage());
} catch (InvocationTargetException exception) {
throw new RuntimeException(“Error in grouping !” + exception.getMessage());
} catch (NoSuchMethodException exception) {
throw new RuntimeException(“Error in grouping !” + exception.getMessage());
}

}
return grupMap;

}

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail