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...