21 Aralık 2012 Cuma

ETL (Extract Transform Load)

ETL ne zaman lazım olur ?
- Bir projeyi ilk defa ayağa kaldırırken mevcut veriyi alıp kendi veri modelimize çevirirken kullanırız.

- Çalışan bir başka sistemin değişen deltasını alıp kendi sistemimize ekleyerek, senkronizasyonu sağlamak amaçlı kullanabiliriz.

- Data warehouse sistemini çeşitli kaynakları kullanarak beslemek için kullanabiliriz.

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




7 Kasım 2012 Çarşamba

Wicket ile Componentler

Bu yazı ile ilgili olarak Wicket ile Formlar başlıklı yazıyı okuyabilirsiniz.

Anladığım kadarıyla Wicket ile görsel olarak sayfada gösterilen herşey Component sınıfından türüyor.

Component LifeCycle
Component yaşamdöngüsü boyunca aşağıdaki metodlar çağırılıyor
Constructor (sadece bir kere çağırılır)
onInitialize (sadece bir kere çağırılır)
onConfigure (görünen/görünmeyen - visible/invisible - her component için her istekte çağırılır)
onBeforeRender (görünen - visible - olan her component için her istekte çağırılır)
onRender (görünen - visible -olan her component için her istekte çağırılır). RESTful Web Services with Wicket sayfasında bu metodun REST tarzı işler için nasıl kulllanıldığını görmek mümkün.
onComponentTag (görünen - visible -olan her component için her istekte çağırılır)
onComponentTagBody (görünen - visible -olan her component için her istekte çağırılır)
anAfterRender (görünen - visible -olan her component için her istekte çağırılır)
onDetach (görünen/görünmeyen - visible/invisible - her component için her istekte çağırılır)
onRemove Bir component hiyerarşiden çıkarılırsa çağırılır. Örneğin bir panel başka bir panel ile yer değiştirirse.
 
Business logic in wicket, where are some recommended places to put logic (on load logic)
sorusunda da benzer bir açıklama var.

Component ve HttpRequest
Her Component sayfaya gelen Http isteğine direkt erişime sahip. Aşağıdaki Http isteğinin işlenmesini gösteren şekli buradan aldım.



Şekilden görülemese de Component sınıfının getRequest() metodu buradaki örnekte gösterildiği gibi kullanılırsa Component veya sayfadan HttpRequest parametrelerine erişmek çok kolay.

Wikcet ile URL
Wicket ile URL kullanarak parametre geçilmek isteniyorsa PageParameters sınıfı alan bir constructor kullanmak gerekir. Bu constructor'ı da http://localhost:8080/myappmypag?id/1 gibi bir URL ile çağırmak mümkün.

Wicket ile Ajax
Ajax ile hatırlanması gereken en önemli kural her Ajax çağrısı XML döndürmelidir. Unable to download file
sorusunda da açıklandığı gibi Ajax ile binary veri döndürülemez.

Aşağıdaki şekilde bir component'e Ajax davranışı eklemenin mümkün olduğu görülebilir.
onchange : Bu event <input type="text"> türü komponentler için fokus kaybedilince çağırılır.
AjaxEventBehavior: Bu sınıf tüm ajax sınıflarının temelini oluşturuyor. Örnek
WebMarkupContainer div=new WebMarkupContainer(...);
div.setOutputMarkupId(true);
div.add(new AjaxEventBehavior("onclick") {
 protected void onEvent(AjaxRequestTarget target) {
     System.out.println("ajax here!");
 }
}
AjaxFormSubmitBehavior : Bu sınıf ile tüm form submit edilir.
AjaxFormComponentUpdatingBehavior : Bu sınıfı sadece form komponentleri ile birlikte kullanılabilir.
AjaxCallDecorator: Form komponentlerine tıklanınca veya Ajax gerektiren bir iş yapılınca çalışacak olan Ajax kodunu atamak için kullanılır. Örneğin IndicatingAjaxLink gibi bir sınıfa eklenen decorator ile linke tıklanınca tüm ekranı bloke eden bir pencere çıkartmak mümkün. Sınıfın bir koşula bağlı olarak kullanım örneğini burada görebilirsiniz.

AbstractAjaxTimerBehavior: Bu sınıf ile timer durdurulmuş vaziyette yaratılır. Daha sonra kullanıcının isteğine göre başlatılabilir. Örneği buradan bulmak mümkün.
AjaxSelfUpdatingTimerBehavior: Bu sınıf ile herhangi bir komponent periyodik olarak güncellenebilir. Örneği buradan aldım.

Wicket ve IAjaxCallDecorator
IAjaxCallDecorator sınıfının kullanımını burada görebilirsiniz.

Wicket ve Behavior Render

beforeRender ve afterRender
Bu metodları kullanarak bir component ekranda gösterilmeden önce veya sonra işlem yapılabilir. Örneğin How to sort the choices in a Wicket dropdown according to the current user locale? sorusunda bir DropDownChoice eklenen Behavior sayesinde verilen listeyi sıralayabiliyor. Generating commented-out content with Wicket sorusunda da güzel bir örnek var.



Wicket ve JavaScript
call javascript or modify css from wicket panel class sorusunda IHeaderContributor arayüzü kullanılarak bir componenet için JavaScript veya CSS kullanabilme örneği verilmiş.


Wicket ve XHTML

XHTML içinde kullanılabilecek wicket tag'lerini burada bulmak mümkün. Benim kullandıklarımsa:

wicket:id - xhtml içindeki aynı id'ye sahip tag bir component ile eşleştirilir. Label gibi basit componentleri eklemek için kullanılır.
wicket:panel - sekme (tab) sayfaları gibi görünür/görünmez yapılabilen componentler için kullanılabilir
wicket:extend - wicket:child ile beraber kullanılır. Şablon sayfaları yaparken kullanılabilir. Şablon olmayan kısımları doldurmaya yarar
wicket:child - Şablon sayfası yaparken şablon olmayan kısımların neresi olduğunu işaretlemeye yarar
wicket:enclosure - Burada açıklandığı gibi ekrandaki bileşenleri gruplayıp, bazı bileşenlerin görünür olup olmamasını grup şeklinde kontrol etmeye yarar.

Wicket ve JSF
Wicket ile JSF'yi karşılaştırırken Wicket Components - have to add() every time? sorusuna verilen cevapta Wicket'ın JSF'nin aksine çok fazla non-html tag kullanmadığı yazılı ki bu doğru bir tesbit. Componentler add() metodu ile Java kodunun içinden ekleniyorlar.

Wicket ile Formlar

HTML ile oluşturulan formların içine konulabilecek elementler burada gösteriliyor.Aşağıya da buradan aldığım bir örnek form resmini ekliyorum.

Peki wicket formlar eklenen elementleri nasıl bir sınıf hiyerarşisine almış ?
Herşey FormComponent sınıfı ile başlıyor. Bu sınıfın altında derin bir hiyerarşi var. Aşağıdaki şekili buradan aldım ve wicket çatısı altında FormComponent'in nereye oturduğunu kabaca görmek mümkün.

WebMarkupContainer
FormComponentlerin türediği WebMarkupContainer isminden de anlaşıldığı gibi kendisi görünür olmayan ancak diğer bileşenleri içerebilen bir sınıf. Apache Wicket and Single Page Application (SPA) - How to create Panels from Menu? sorusunda bu sınıfa başka bir bileşen ekleyip çıkarabilme özelliği gösterilmiş.

Form Submit
Form sınıfının kendi onSubmit metodu var. Bu metod ile formun modeline erişmek mümkün. Örnek :
@Override
protected void
onSubmit() {
    Item item = (Item) getModelObject();
    dao.storeItem(item);
    setResponsePage(page);
}
Form İşleme Silsilesi
Bir form submit edilince buradan aldığım şekilde de görüldüğü gibi bir işlem silsilesinden geçiyor.


Bir formu submit etmek için aşağıdaki sınıflar kullanılabilir

SubmitLink, AjaxSubmitLink, Button, AjaxButton sınıfları ile gönderilen bilginin Converter veya Validator'lerden geçmeden ve de model nesnelerini güncellemeden çalışması için setDefaultFormProcessing metodunun false parametresi ile çağırılması gerekir. Simple way to reload page with form data filled with previous data sorusundan aldığım cevap aşağıda.


Converter
Wicket ile kullanılan Converter'ların ilişkisini gösteren bir şekli aşağıya ekledim.
How Wicket models works with generic? sorusunun cevabında da DefaultConverter daha iyi açıklanıyor.

Aşağıdaki kod parçasını buradan aldım ve bir converter'ın application sınıfına nasıl eklendiği ve nasıl çalıştığını gösteriyor.

Form işlenirken formdaki tüm komponentlerin convertInput() metodu çağırılır. Her komponent HTML ile gelen ham stringi bir Java nesnesine çevirir. Eğer çevirme işlemi başarılıysa form işleme silsilesi devam eder. Buradan aldığım açıklama da faydalı.

Validator
Burada dikkat edilmesi gereken nokta "Validate Input"  adımında IValidator arayüzünden türeyen sınıfların kullanılması. Eğer istenirse bu arayüzden başka sınıflar türeterek doğrulama işlemini yapmak ta mümkün.

Aşağıdaki şekilde notlarımı görebilirsiniz.
StringValidator
Bu sınıf ile girilebilen veriye üst sınıf koyabiliriz. Örnek :
TextArea<String> comments = new TextArea<String>("comments");
comments.add(StringValidator.maximumLength(250));

Form Input Elementlerine Özellik Eklemek
AttributeModifier sınıfı ile bir komponente yeni özellikler eklemek mümkün. Örneğin Label sınıfına tooltip eklemek için Display Wicket panel content as tooltip on mouse hover of a page component sorusundaki kod kullanılabilir.


Form Input Elementleri

Bu başlık altında wicket ile kullanılabilen form elementlerine bakacağım.

AutoCompleteTextField
Aşağıda AutoCompleteTextField elementinin sınıf hiyerarşisini görmek mümkün. Tek yapılması gereken getChoice metodunu yazmak.
Button
Her formda submit işlemini yerine getiren bir button bulunur.

CheckGroup
Aşağıda CheckGroup'un nasıl kullanılacağını gösteren bir şekil var.

Wicket : Check of CheckGroup not getting the selected options and perform the submit actionsorusunu daokumak faydalı.

CheckBox
How to unselect checkbox in chrome browser sorusundan aldığım örnek aşağıda.
Html için :

<input type="checkbox" wicket:id="1" />
Java için ise :
Checkbox c1 = new CheckBox("1").setOutputMarkupId(true);
c1.add(new AjaxFormComponentUpdatingBehavior("onclick"){
    protected void onUpdate(final AjaxRequestTarget target) {
        if (Boolean.TRUE.equals(c1.getModelObject()){
            c2.setModelObject(Boolean.FALSE);
            c3.setModelObject(Boolean.FALSE);
            target.addComponent(c2);
            target.addComponent(c3);
        }
    }
});

Wicket checkbox that automatically submits its changed value to domain object sorusunda ise checkbox her değiştiğinde belli bir kod parçası çalışsın isteniyorsa wantOnSelectionChangedNotifications() metodunun kullanılması gösterilmiş.

DateTime
DateTime için wicket-extensions kütüphanesinde iki seçenek var. Birincisi org.apache.wicket.extensions.yui.calendar.DateTimeFied.

Diğeri ise wicket.extensions.markup.html.form.DateTextField ve bununla beraber kullanılan org.apache.wicket.extensions.yui.calendar.DatePicker ise popup takvim gösterimini yapıyor.Bu sınıf ta YUI kütüphanesini kullanıyor. DateTextField kullanmak için aşağıdaki gibi bir html lazım.


Bu yazı devam edecek...

26 Eylül 2012 Çarşamba

Wicket Deployment Mode

 Wicket Deployment Mode ve ExceptionSettings

Wicket atanan deployment moduna göre yakalanmamış runtime exception'ları işlemektedir.
Eğer deploment mode RuntimeConfigurationType.DEVELOPMENT ise yakalanmamış exceptionlar stack trace bilgisi ile gösteriliyor.

Ancak Eğer deploment mode RuntimeConfigurationType.DEPLOYMENT ise yakalanmamış exceptionların stack trace bilgisi gösterilmiyor.

How can I see stack traces for my Wicket app? başlıklı soruda da cevaplandığı gibi DEPLOYMENT mod ile exceptionları göstermek için uygulamanın ExceptionSettings ayarları değiştirilebilir.

Eğer Wicket filter olarak kullanılıyorsa buradan aldığım şekildeki gibi web.xml dosyasından deployment mod da atanabilir.

Aşağıda bu sınıfın diğer sınıflar ile ilişkisi ve uygulama açılırken nereden okundğunu gösteren bir şekil bulabilirsiniz.


19 Eylül 2012 Çarşamba

Spring ve Factory Bean

Spring içindeki bazı FactoryBean sınıflarına örnekler. Collections başlıklı yazıya bakmakta da fayda var.

ListFactoryBean
ListFactoryBean sınıfı ile ilgili gördüğüm güzel bir cevap how does the <list> tag work in spring başlıklı soruda var.

Buradan aldığım örnekte List yaratan bir ListFactoryBean örneği var.


13 Eylül 2012 Perşembe

Hibernate hbm2ddl

Hibernate ile hbm2ddl isminde bir araç geliyor. Bu araç ile ilgili bulabildiğim en iyi yazılardan birisi Eyal Lupu tarafından yazılmış olan Hibernate's hbm2ddl tool başlıklı yazı.

Bu aracı kullanmak için konfigürasyon dosyasına

hibernate.hbm2ddl.auto = validate | update | create | create-drop seçeneklerinden birisini yazmak gerekiyor.

Aşağıdaki örnekte tablolar otomatik olarak yaratılıyor.

<hibernate-configuration>
    <session-factory>
        <property name="hbm2ddl.auto">create</property>
    </session-factory>
</hibernate-configuration>

Index Yaratma
Creating Indexes on DB with Hibernate @Index Annotation başlıklı soruda güzel bir cevap var.

Constraint Yaratma
@UniqueConstraint JPA anotasyon açıklaması ise burada.

12 Eylül 2012 Çarşamba

Apache Wicket ve Spring


Yazıya başlamadan önce hem Apache Wicket hem de Spring'in  bir servlet container içinde çalıştığını unutmamak lazım. Dolayısıyla ilk yapılması gereken iş, Servlet container ile bu iki yazılımı birleştirmek olmalı.

Spring ve Servlet Container


Spring ile Servlet Container'ı birleştirmeyi buradan aldığım şekil güzel açıklamış. Servlet Container bir spring sınıfı olan org.springframework.web.context.ContextLoaderListener sınıfını kullanarak Spring'i ayağa kaldırır. org.springframework.web.context.ContextLoaderListener sınıfının hiyerarşisi aşağıda.




ContextLoaderListener web.xml dosyasına aşağıdaki gibi tanımlanır.

ContextLoaderListene sınıfının okuması gereken dosyalar ise aşağıdaki gibi tanımlanır.

Burada okunacak dosyanın WEB-INF dizini altında olduğuna dikkat etmek lazım. Çünkü war dosyasının yapısı aşağıdaki gibi.

ContextLoader okuması söylenen dosyaları aşağıdaki şekildeki gibi okur ve Spring framework çalışmaya başlar.

Spring ayağa kalkınca herşeyin kalbi olan "ApplicationContext" nesnesini bir yerde saklaması gerekir. Bu iş için de ServletContext arayüzünü kullanır. Bu durumu gösteren şekli buradan aldım.

ServletContext içinde bir nesne saklanmasını göstern örnek kodu buradan aldım.

// following method is invoked one time, when you web application starts (is deployed)
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    // ...
    final int numberOfThreads = ...;
    final ExecutorService threadPool = Executors.newFixedThreadPool(numberOfThreads); // starts thread pool
    final ServletContext servletContext = servletContextEvent.getServletContext();
    servletContext.setAttribute("threadPoolAlias", threadPool);
    // ...
}

// following method is invoked one time when your web application stops (is undeployed)
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    // following code is just to free resources occupied by thread pool when web application is undeployed
    final ExecutorService threadPool = (ExecutorService) servletContextEvent.getServletContext().getAttribute("threadPoolAlias");
    threadPool.shutdown();
}

Apachet Wicket ve ServletContainer

 Apache Wicket ile ServletContainer'ın nasıl birleştiğini aşağıdaki şekil gösteriyor.
Daha sonra javax.servlet.ServletContext nesnesine erişmek için Wicket Notes yazısındaki kod parçası kullanılabilir.


Eğer bir war dosyası içindeki relative path kullanmak istiyorsak Wicket - Relative Image Path without Mounting Page sorusundaki gibi UrlUtils.rewriteToContextRelative metodu kullanılabilir. context.getRealPath() metodu /MyApp gibi bir dizin döndürdüğü için rewriteToContextRelative  metodu /MyApp/images/img1.png gibi bir path döndürür. Aşağıda war dosyasının dizin yapısı görülebilir.


Benzer bir işi How do i link to my Image-Folder inside my Apache Wicket Application? sorusunda cevaplandığı gibi ContextRelativeResource sınıfını kullanarak ta yapabiliriz.
  Apachet Wicket içinden Spring ApplicationContext'e erişmek


Spring ile entegre olmak için wicket-spring.jar dosyasının projeye dahil edilmesi gerekiyor.


Apache Wicket ve Spring'i birbirine entegre etmek çok kolay. Nasıl yapılacağı burada anlatılıyor.

Not : Spring ve Bean Yaratılması başlıklı yazıda Spring Container'ın çalışması ile ilgili biraz daha detaylı bilgi bulabilirsiniz.

1. Annotation Yöntemi

En kolay yöntem de Annotation Based Approach paragrafında anlatıldığı gibi yapmak. Aşağıda buradan aldığım @SpringBean anotasyonu kullanılan örnek bir kod parçası var.


Spring-Wicket: optional but named bean still required sorusunda da anlatıldığı gibi @SpringBean ile required=false kullanarak enjeksiyonu engellemek te mümkün.

2. Kod İle Elle Enjeksiyon Yöntemi
 
Yalnız bu dokümanda dikkat edilmesi gereken bir nokta var. Örnekte de verildiği gibi SpringComponentInjector sınıfı sadece Wicket Component'ları yaratıldığı zaman çağırılan bir listener.Aşağıdaki şekilde bir Component yaratılınca nasıl listener'ın çağırıldığını görmek mümkün.



Halbuki Wicket içindeki her sınıf Component sınıfından türemiyor. Örneğin Model sınıfı gibi. Aşağıdaki şekli buradan aldım ve Component hiyerarşisini kabaca gösteriyor.



Bu durumda model sınıfında @SpringBean anotasyonu kullanılsa bile işe yaramaz.Bunun yerine


InjectorHolder.getInjector().inject(this)

kodunu kullanmak lazım.

Bu da Wicket'ın bir azizliği işte. Bir çok yazılım çatısında da çatıdaki her sınıfın ortak bir atadan türemediğini gördüm. Burada da aynı durum var ve nadiren de olsa bazen normal kullanımdan sapmayı gerektirebiliyor.

3. Kod İle ApplicationContext Nesnesine Erişim Yöntemi

Yukarıda kod ile enjeksiyon yönteminde enjekte edilecek nesnelerin sınıfın bir üyesi (member attribute) olması gerekiyor. Eğer bunu da istemiyorsak ve metod içinde kullanmak üzere ApplicationContext nesnesine erişmek istersek Spring bize kolaylık olması için WebApplicationContextUtils isimli sınıfı kullanılabilir.

Aşağıdaki örnekte olduğu gibi Wicket'ın Application sınıfından ApplicationContext nesnesine erişim mümkün.

public ApplicationContext getContext() {
        return WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
 }


Wicket Stateful ise Spring ile Nasıl Entegre Oluyor ?

Wicket statefull bir yazılım. Bu durumu anlatan güzel bir örneği burada bulabilirsiniz. Bu basit örnekte aynı safya defalarca tazelendiği halde Wicket'ın nasıl stateful çalıştığı anlatılmış. Aslında Wicket bir oturum içinde gösterilen tüm sayfalar için state tutuyor. Bu durumu gösteren güzel bir şekli buradan aldım.


Bu çalışma modeli bir sayfa'nın içindeki herşeyin Serializable olmasını gerektiriyor. Peki bu durumda sayfaya enjekte edilen Spring Bean'lerin de Serializable olması gerekmiyor mu ? Hal böyle ise bir bean ve onun bağımlı olduğu tüm beanlerin de yazılması gerekir.

Eğer böyle olsaydı Wicket Spring ile hayatta entegre olamazdı. @SpringBean ile enjekte edilen sınıf aslında bir proxy. Dolayısıyla @SpringBean ile Spring Framework'teki kullanımın aksine sadece interface kullanılabilir. Sayfa da session'a yazılınca üretilen proxy yazılıyor, atıfta bulunduğu Spring Bean sınıfı değil. Bu durumu açıklayan güzel bir soruyu burada buldum. Yine aynı konuya değinen güzel bir cevabı da burada buldum.. Bir diğer açıklama ise Double-click seems to disrupt Wicket-Spring injection sorusunda açıklanmış.