2 Ocak 2013 Çarşamba

İş Zekası

Aşağıda iş zekası ile ilgili aldığım notlar var.

Fact Table
Türkçesi Olgu Tablosu. Fact Table genel bilgilerinin tutulduğu ,tarihsel derinliği olan ve milyonlarca kayıt sayısına sahip olabilecek tablodur.

Dimension
İngilizcede "By X" içeren cümleler Dimension tablosudur. Dimension tablosundaki tek bir satır, Fact Table'daki n tane satır ile eşleşir. Eşleştirme için Surrogate Key kullanılır. Surrogate Key ile ilgili olarak Hibernate ile Birincil Anahtar ve GeneratedValue kullanımı başlıklı yazıya bakabilirsiniz.

14 Aralık 2012 Cuma

Değer Atanmış Tarih Nesnesi Yaratma

Belli bir tarih ve saat atanmış olarak bir nesnesini yaratmakla ilgili notlarım aşağıda.

Joda
Joda ile belli bir tarihi atamak için aşağıdaki yöntemlerden birisi kullanılabilir.
 Örneğin JDK Date nesnesi atanmış bir tarih yaratmak için aşağıdaki yöntem kullanılıyor.


11 Aralık 2012 Salı

Spring ve Bean Yaratılması

Not : Dependency Injection sınıflar arasındaki bağımlılığı azaltırken altyapıya olan bağımlılığı artıyor.
Dependency injection increases coupling by requiring the user of a subsystem to provide for the needs of that subsystem.

1. Spring İçindeki Olayları Dinlemek

Spring Container da diğer tüm container tarzı yazılımlar gibi, kendisine abone olunup Observer tasarım örüntüsünün kullanılmasına imkan tanımaktadır. Bu durumu gösteren şekli buradan aldım. Böylece ApplicationListener arayüzü vasıtasıyla bir çok olayı öğrenmek mümkün.



2. Spring ve Bean'lerin Yaratılması

2.1 Bean Yaratılmadan Önce

Aşağıdaki şekli buradan aldım. Bean yaratılmadan önce BeanFactoryPostProcessor ile bean tanımında değişiklik yapabilmek mümkün.



Aşağıdaki şekilde ise BeanFactoryPostProcessor arayüzünden türeyen bazı sınıfları görmek mümkün.


2.2 Bean Yaratıldıktan Sonra

Spring içindeki bean'lerin yaşam döngüsünü (lifecycle) bir nebzeye kadar detaylandırmak mümkün. Bunun için kullanılabilecek 3 yöntem var.

  1. BeanPostProcessor Yöntemi
  2. XML içinde Custom Metod  Yöntemi
  3. InitializingBean ve DisposableBean Yöntemi
BeanPostProcessor Yöntemi
Bu başlığı ikiye ayırmak lazım. Birincisi Spring içinde tanımlı olan BeanPostProcessor sınıfları, ikincisi ise kendi tanımladığımız sınıflar.
Spring içinde tanımlı olan BeanPostProcessor sınıfları
BeanPostProcessorYöntemi burada anlatılıyor. Örneğin <tx:annotation-driven> XML cümlesi ile BeanPostProcessor yöntemi aracılığıyla transaction yönetimi gerçekleştiriliyor. Bir bean yaratılmadan önce bir BeanPostProcessor @Transactional anotasyonu kullanılmışmı diye kontrol ediyor ve eğer kullanılmışsa yaratılmak istenen bean için bir proxy üretiyor.

Bir başka örnek olarak org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor sınıfına da bakılabilir. Bu sınıf ile ilgili güzel bir örnek te burada bulunabilir.

Bu sınıf sayesinde @Autowired, @Inject, @Resource gibi tagler kullanılabiliyor.

Bu sınıfı Spring'e dahil etmek için <context:annotation-config /> veya <context:component-scan> XML cümlelerini eklemek yeterli. Bu ikisi arasındaki farkı anlamak için Difference between <context:annotation-config> vs <context:component-scan> başlıklı yazıya bakabilirsiniz.

<context:component-scan> ile @Component, @Repository, @Service ve @Controller olarak işaretli bean'ler Spring'e dahil ediliyor. Eğer bu taglerden bazılar hariç bırakılmak istenirse aşağıdaki gibi yapılabilir.

<context:component-scan base-package="com.java.test.app org.java.support">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

Kendi Tanımladığımız BeanPostProcessor Sınıfları
Buradaki örnekte Spring ile yaratılan bir bean nesnesinin Guava EventBus nesnesine eklenmesi örneği var.
 

Custom Metod Yöntemi
Bu yöntemde XML içinde bean'in çağırılacak metodu belirtliyor.

InitializingBean ve DisposableBean Yöntemi
Bu yöntemde bean InitializingBean ve DisposableBean arayüzlerinde türetiliyor.

Yöntemler arasında öncelik sırası bulunmakta. Bu öncelik sırasını gösteren bir şekli burada buldum.

Görüldüğü gibi InitializingBean arayüzü tarafından istenen afterPropertiesSet() metodu custom init metodundan önce çağırılır. Aynı zamanda DisposableBean arayüzü tarafından istenen destroy() metodu da yine custom destroy metodundan önce çağırılır.



Benzer bir şekli ise burada buldum.


InitializingBean yöntemi Spring'e mahsus. JSR-250 ile @PostConstruct ve @PreDestroy  tagleri tanımlanmış. Using JSR-250's @PostConstruct Annotation to Replace Spring's InitializingBean başlıklı yazıda da anlatıldığı gibi Spring'e mahsus bu arayüzler yerine @PostConstruct ve @PreDestroy anotasyonlarının kullanımı tercih edilmelidir.

2.3 new() ile Yaratılan Bean'ler
How to inject dependencies into a self-instantiated object in Spring? sorusunda da cevaplandığı gibi AutowireCapableBeanFactory arayüzü kullanılarak manuel olarak yaratılmış olan bir bean'e de dependency injekte edilebilir.


2.4 Bean ve Yaratılış Kapsamı (Scope)

Spring ile default gelen scope singleton scope'tur. Yani container bir bean'i bir defa yarattıktan sonra onu önbellekte saklar ve tekrar istenirse yine aynı nesneyi döndürür. Bu durum gösteren bir şekli buradan aldım.

Konuyu daha iyi açıklayan bir örneği ise burada bulabilirsiniz.


19 Kasım 2012 Pazartesi

Hibernate ve İkincil Önbellek

İkincil Önbellek
 
İkincil önbellek ile ilgili data detaylı bilgiyi burada bulabilirsiniz.
İkinci önbellek aslında 4 kısımdan oluşuyor. Bunlar entity, collection, query ve timestamp kısımları. Hibernate ikincil öbelleği kullanmak üzere ayarlanırsa bu alanları otomatik olarak oluşturuyor ancak bu alanlara ne kadar bellek ayırılacağı vs. gibi ince detaylar önbellek kütüphanesinin konfigürasyon dosyasında yapılıyor. Örneği burada görebilirsiniz.

İkincil Önbellek Hibernate Sessionları Arasında Ortak Kullanılır

Aşağıdaki şekli buradan aldım ve farklı Hibernate sessionları arasında önbelleğin ortak kullanıldığını görmek mümkün.


Hemen hemen aynı şeyi gösteren bir başka şekil ise buradan geldi.

İkincil Önbelleği Etkinleştirme Ayarları
İkincil önbelleği konfigüre etmek için gereken ayarları gösteren kısmı buradan aldım.

<property name="hibernate.cache.use_second_level_cache">
true</property>
<property name="hibernate.cache.use_query_cache">
true</property>
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider</property> 
 
1. Entity Önbellek Ayarları

En kolay yöntem annotation kullanmak. Hibernate annotationları kullanılmak istenirse @Cache kullanılıyor. Eğer JPA annotation kullanılmak istenirse @Cacheable kullanılıyor.

Not : Entity Önbellekte entity'nin primary key değeri arama anahtarı olarak kullanılıyor

Eğer entity'ler InheritanceType.TABLE_PER_CLASS stratejisini kullanıyorsa @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) tag'ini en alttaki sınıfa eklemek gerekiyor.
Yoksa aşağıdaki şekilde de görüldüğü gibi Hibernate accessStrategy sınıfını bulamıyor ve entity ikincil önbelleği kullanamıyor





İkincil Önbellek Stratejileri
Bu konuyla ilgili fazla bilgi bulamadım. Kullanılabilecek stratejiler aşağıda.
NONE :

READ_ONLY : Eğer nesneler hiç değişmiyorsa, değeri hep sabit ise kullanılır

NONSTRICT_READ_WRITE : Çok nadiren değişen nesneler için kullanılır. Eşzamanlı güncellemeler için önbellekte lock mekanizması kullanmaz. Dolayısıyla önbellekten dönen sonucun her zaman en son güncellenen değer olduğunu garanti etmez!

READ_WRITE : En çok kullanılan yöntem.

TRANSACTIONAL : Sadece XA transaction yöneticisi varsa bu seçenek kullanılabilir

İkincil Önbellek Boşaltma Yöntemleri

İkincil önbellek boşaltılması ile ilgili kurallar aşağıda.

sessionFactory.close() –> Destroys the session factory object and releases level 2 cache.
sessionFactory.evict(arga …) –> Removes pojo class object from session factory.
sessionFactory.evictQueries(args…) –> Cleans queries related data from cache.

Evict örneklerini gösteren bir kodu buradan aldım.


İkinci kademe önbellekte entitiy kısmında arama yapılmasını anlatan örneği buradan aldım.


2. Sorgu Önbellek Ayarları
Sorgu önbelleğinin neden aslında zararlı olabileceği ise burada anlatılıyor. Sorgu önbelleği çalışma akışı ise aşağıda.


Not : Sorgu Önbellekte anahtar olarak sorgunun kendisi ve sorguya verilen parametreler arama anahtarı kullanılıyor

Sorgu Önbelleği Tabloların Değişip Değişmediğini Nasıl Anlıyor?
Buradaki soruda da anlatıldığı gibi sorgu çalıştırılmadan önce sorguyu ilgilendiren tabloların UpdateTimestampsCache önbelleğindeki en son güncellenme zamanına bakılıyor. Eğer tablolar önbellekteki sorgu sonucundan sonra güncellenmişse, sorgu tekrar çalıştırılıyor.

16 Kasım 2012 Cuma

Wicket ve Dosya İndirme

IResourceHandler - İndirilecek olan kaynağı akım olarak gönderir
Bu arayüzü gerçekleştiren sınıf ResourceStreamRequestHandler sınıfı. Bu sınıf IResourceStream kaynağını okur ve servlet'in çıktısı olarak gönderir.
//ResourceStreamRequestHandler aşağıdakine benzer bir iş yapar
ServletOutputStream servletOutputStreamObj = response.getOutputStream();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=\"" + strFileName + ".xls\"");
Eğer indirilen dosya browser içinde gösterilsin istiyorsa aşağıdaki gibi yapabiliriz.
response.setHeader("Content-Disposition","inline");
ResourceStreamRequestHandler Kullanımı
ResourceStreamRequestHandler sınıfıBir komponent'in onClick() metoduna aşağıdaki gibi bir kod yazılabilir.

ResourceStreamRequestHandler mergedFileHandler = new ResourceStreamRequestHandler(new FileResourceStream(mergedFiles));
mergedFileHandler.setFileName(mergedFiles.getName());
getRequestCycle().scheduleRequestHandlerAfterCurrent(mergedFileHandler);
Bu tür detaylarla uğraşmak yerine bunları bizim için yapan ResourceLink veya DownloadLink yöntemlerinden birisi kullanılabilir.

ResourceLink - Sabit veya Dinamik Kaynakların Alınabilmesi
ResouceStreamResource sınıfı IResource kaynağının dinamik olarak alınabilmesine imkan sağlar.
ResourceLink (new ResourceStreamResource(new AbstractResourceStreamWriter())); 

 DownloadLink - Sabit Kaynakların Alınabilmesi
Eğer bir dosya indirilecekse DownloadLink kullanılabilir. Örnek:
add(new DownloadLink("download", new AbstractReadOnlyModel<File>() {
            @Override
            public File getObject() {
                File tempFile;
                try {
                    tempFile = //Create file;
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
                return tempFile;
            }
        }).setDeleteAfterDownload(true);
Bu örnekte DownloadLink kendi içinde IResourceStream sınıfından türeyen FileResourceStream sınıfını kullanıyor.

Link
Bir Link sınıfının onClick metodunda
 getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);

kodu çalıştırılarak indirme işlemi başlatılabilir.


IResourceStream (İndirilecek kaynağı akım haline getirir)
Wicket ile dosya indirmek için aşağıdaki sınıf yapısı temel alınabilir.


Aşağıda ise kendi ResourceStreamWriter sınıfımızı yazmak istersek kullanabileceğimiz hiyerarşi bulunuyor.


IResource
Wicket ByteArrayResource only downloadable: can I let the browser handle the MIME type?
başlıklı soruda IResource'tan türeyen ByteArrayResource ile ilgili bir soru var.İlgili hiyerarşi aşağıda.
Eğer Resource dinamik olarak üretilen bir kaynaksa ResourceStreamResource sınıfı kullanılır.

IRequestCycle
IRequestCycle arayüzünü gerçekleştiren sınıf RequestCyle sınıfı. Bu sınıfın setResponsePage metodunun iki farklı çeşidi var. İlki bir Class alıyor, diğeri ise bir IRequestablePage instance'ı alıyor. Aralarındaki fark burada açıklanıyor. İlk metod 302 tarayıcıya redirect komutu gönderiyor.

RequestCycle in Wicket 1.5 sayfasında açıklandığı gibi dosya indirme işleminin gerçekleşmesini sağlayan  RequestCycle sınıfı. Bu sınıf ile gösterilecek bir sonraki sayfayı veya gösterme işlemi bittikten sonra indirilecek dosyayı belirtiyoruz. Örneğin gösterilecek bir sonraki sayfa için
setResponsePage(getApplication().getHomePage());
veya

add(new Link<Void>("link-login") {
  @Override
  public void onClick() {
    setResponsePage(LoginPage.class);
  }
});
metodunu çalıştırsak bile aslında altta aşağıdaki kod çalışır.
How to server-side forward a page request with Wicket 6 sorusunda ise konuyla ilgili açıklama var.


Bookmarkable vs non-bookmarkable pages
Page navigation within the controller başlıklı yazıda anlatıldığı gibi eğer bookmarkable bir sayfa göstermek istersek aşağıdaki gibi yaparız.
Eğer non-bookmarkable bir sayfa göstermek istersek aşağıdaki gibi yaparız.

14 Kasım 2012 Çarşamba

Wicket ile Tablo ve Izgaralar

Wicket ile tablo ve ızgaralar konusu burada açıklanmış. Konuyu tam kavrayamadım ancak arada şöyle bir fark var sanırım.

DataView : provider'dan gelen veriyi satir satir doldur. data sort edilmek istenirse ek kod lazım.

GridView : provider'dan gelen veriyi sutun sutun doldur. data sort edilmek istenirse ek kod lazım.

DataGridView : provider'dan gelen veriyi sutun sutun doldur ama datayı sort edebilme imkanını hazır olarak tanıma. Hatta datayı sadece metin olarak gösteriyor sanırım.

DataTable : provider'dan gelen veriyi sutun sutun doldur ve toolbarlar ile datayı sort edebilme imkanı tanı. Veri çeşitli şekillde formatlanabilir.Bir DataTable yaratmak için aşağıdakine benzer kod lazım.

DataTable exampleTable = new DataTable(...)
exampleTable.addTopToolbar (new HeadersToolbar(...));
exampleTable.addBottomToolbar (new NavigationToolbar(exampleTable));
add(exampleTable);

DefaultDataTable : hazır bir data table