Bu yazıda google’ın open source olarak piyasaya sürdüğü ve giderek telefonlarda görmeye başladığımız Android işletim sistemine application(uygulama) yazmak için ilk adımları atacağız.
- 1. Android hakkında kısa bilgi
- 2. Android Application yazma hakkında bilgi
- 3. Android SDK kurulumu
- 4. Eclipse ve ADT(Android Development Kit) plugin kurulumu
- 5. Creating “Hello Android” app
- 6. Virtual Device’da applicationı test etme
Android linux çekirdeğini kullanan mobil cihazlar için open source işletim sistemidir. Android'in SDK'sı Java ile program geliştirme araçlarını ve API'lerini sağlamaktadır. Sağladığı genel özellikler :

Ben windows altında çalışma ortamımı oluşturacağım. İndirdiğimiz dosyayı çalışma ortamımıza çıkartıyoruz. Daha sonra klasörün içindeki "SDK Setup" ı çalıştırıyoruz. Ufak bi ayar yapmamız gerekmekte.

https ile genelde çalışmıyor. Bu yüzden böyle bir ayar yapıyoruz. Devamında :

Intalled package'a gelip update all diyoruz.

Burada önceki Sdk'ları yüklememize gerek olmadığı için ben screenshot'daki 4ünü seçtim. Install Accepted diyerek devam edelim.


Ve SDK kurulumda Son:

Şimdi Eclipse ortamını hazırlayabiliriz. Eclipse'in yeni sürümleri kullanmamız gerekiyor. (3.4 ve sonrası) Eclipse'i açıyoruz.
ADT Pluginini kuralım. bunun için:

Help > Install New Softare daha sonra gelen ekrandan Add e tıklayalım.

Sonra ekrandaki name alanına Android App yazabilirsiniz. Location alanına da
"http://dl-ssl.google.com/android/eclipse/" giriyoruz. Daha sonrası Next Next olayı.
Eclipse kapatılıp açılacaktır, açıldıktan sonra ADT araçları göreceksiniz. ARTIK ÇALIŞMA ORTAMIMIZ HAZIR. Şimdi ilk uygulamamızı yazalım.
------------İlk Örneğimiz HeLLO Android ----------
Bunun için eclipse deFile > New > Project diyoruz.
Android Project'i seçiyoruz.
Gelen ekrandan gerekli alanları dolduruyoruz. Burada;
- Project Name
- Eclipse de oluşturduğumuz projenin adı.
- Application Name
- Android uygulamasının üzerinde görülecek olan isim
- Package Name
- Javadaki package yapısı ile aynı
- Create Activity
- İlk başta package altında açılacak olan class'ın adı. (Opsiyonel)
Şimdi com.jtpd.helloAndroid altındaki HelloAndroid.java class'ını açalım.

Tüm olay bu kadar basit. Şimdi de çalıştırıp Virtual Device da test edelim. Bunun için Run as -> Android Applicaton seçiyoruz.
Şimdi de Uygulamamıza ekleme yapalım.




Umarım basit bir olayı karmaşıklaştırmamışımdır. Yazıyı oluştururken yararlandığım kaynak http://developer.android.com .
Bileşen bazı web çatısı (Component Based Web Framework) olan Apache Wicket ile kendimize ait bileşenler oluşturmak çok kolay. Web uygulamalarımızda çok kullandığımız kullanıcı yönlendirici mesajları göstermek için bir Wicket Bileşeni nasıl oluştururuz gelin hep birlikte görelim.
[--split--]
Apache Wicket ile Bileşen Tabanlı (Component Based) Web uygulaması gerçekleştirmek kolay ve zevkli bir iş haline geliyor. Bir iki klavye hamlesi ile AJAX uygulaması yazabilirsiniz.
Uygulamalarda kullanıcı bilgilendirme mesajları kimi zaman ilgili formun üzerinde, form girişlerinin yanında ve ya ayrı sayfalarda gösterilmektedir. Bu mesajların gösterimindeki görsel uyumluluk kullanıcının mesajı okumadan içeriği hakkında bilgi sahibi olmasını sağlar. Yönlendirme düğmeleri (button) kullanılarak hangi işleme devam etmesi seçenek olarak sunulur.
Aşağıdaki gibi bir mesaj kutusu tasarladım.
1. SUCCESS, INFO, WARNING, ERROR ve UNAUTHORIZED şeklinde 5 tip mesaj gösterebiliriz.
2. Her mesaj tipinin kendisine ait logosu olacak.
3. Bazı genel mesajlarda title ve footer alanı olmayacak.
4. İstediğim kadar yönlendirme düğmesi ekleyebilmeliyim.
Çizmiş olduğumuz arayüz tasarımını, tasarımcıya verip HTML ve CSS kodlamalarını gerçekleştirelim.
HTML kodları içerisinde Apache Wicket bileşenlerine wicket:id eklemesini yapalım.
Wicket bileşenleri:
1. Mesaj Logosu
2. Mesaj Başlık Panel’i
3. Mesaj Başlığı (Title)
4. Mesaj Gövdesi (Body)
5. Mesaj Sonu (Footer)
6. Yönlendirme Düğmeleri (Buttons)
<div class="msg_container">
<div class="msg_body">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="160"><img wicket:id="logo"/></td>
<td><div wicket:id="titlePanel"></div>
<br /><span wicket:id="body">[body]</span><br />
<br /><span wicket:id="footer">[footer]</span><br />
<br />
<br />
<div style=" margin-right: 30px;">
<div wicket:id="buttons" style="float:right; margin-right:15px;" >
<input type="button" wicket:id="button"/>
</div>
</div>
<div style="clean: both"/>
</td>
</tr>
</table>
</div>
</div>
</wicket:panel>
Neden mesaj başlığını bir panel içerisine koyuyoruz? Cevabı basit, başlığı olmayan bir mesaj göstermek istediğimde gövdenin yukarısında göze batacak kadar boşluk olmasını istemiyorum. Bu yüzden burada bulunan div’i gizlemem gerek. Bunun için de başlığın bulunduğu div’e bir wicket panel’i olarak işlem yapacağım.
<strong style="color: #007087;">
<span wicket:id="title">[title]</span>
</strong><br />
</wicket:panel>
UML Sınıf Diyagramım aşağıdaki gibi olacaktır:
Gösterilecek olan başlık anahtarını, içerik anahtarını (ResourceBundle Key), düğmeleri taşıyacak Message sınıfı oluşturdum.
private MessageType type;
private String bodyKey;
private String footerKey;
private List
public Message(MessageType type, String titleKey, String bodyKey,
String footerKey) {
this.type = type;
this.titleKey = titleKey;
this.bodyKey = bodyKey;
this.footerKey = footerKey;
}
public void addButton(MessageButton button){
this.buttons.add(button);
}
...
}
Gösterilecek olan mesajın tipine göre logo değişimi olacaktır. Bu yüzden resim tanımlarını mesaj tipi ile ilişkilendirdim. Bunun için Enum yapısını kullanabiliriz. Eğer renk farklılığı da olması istenirse CSS tanımlarını da burada kullanabiliriz.
ERROR(ConfirmMessagePanel.ERROR_IMAGE),
INFO(ConfirmMessagePanel.INFO_IMAGE),
SUCCESS(ConfirmMessagePanel.SUCCESS_IMAGE),
WARNING(ConfirmMessagePanel.WARNING_IMAGE),
DENIED(ConfirmMessagePanel.DENIED_IMAGE);
private ResourceReference image;
private MessageType(ResourceReference image){
this.image = image;
}
public ResourceReference getImage(){
return this.image;
}
}
MessageButton soyut sınıfından oluşturacağımız her nesnenin kendine özel davranışı olacaktır. Bu yüzden soyut clickButton yordamı tanımladık. AjaxLink Wicket yapısını kullanarak butonların HTML Button’u olarak işlem görmesini Form Submit Button’u olarak tanımlanmamasını sağlarız. Parametre olarak aldığımız AjaxRequestTarget nesnesinin addCompenent() yordamını kullanarak bize Ajax Call’u sonunda hangi bileşenlerin yeniden yorumlanacağını (rendering) ve yeni HTML kodu üretileceğini belirleriz.
public MessageButton(String labelKey) {
super("button", new Model(labelKey));
this.add(new SimpleAttributeModifier("value",
new ResourceModel(labelKey).getObject()));
}
public abstract void clickButton(AjaxRequestTarget target);
@Override
public void onClick(AjaxRequestTarget target) {
this.clickButton(target);
}
}
Gelelim mesajlarımızı ve diğer görsel bileşenleri Wicket Panel ile göstermeye. Bunun için Panel Wicket yapısından türemiş MessagePanel sınıfını oluşturmalıyız.
private static final long serialVersionUID = -3432489401302616102L;
private ConfirmMessageModal modal;
/** reference to the confirmbox's css resource */
private static final ResourceReference CSS = new ResourceReference(
MessagePanel.class, "confirmbox.css");
/** reference to WARNING image */
static final ResourceReference WARNING_IMAGE = new ResourceReference(
MessagePanel.class, "WARNING.gif");
/** reference to INFO image */
static final ResourceReference INFO_IMAGE = new ResourceReference(
MessagePanel.class, "INFO.gif");
/** reference to ERROR image */
static final ResourceReference ERROR_IMAGE = new ResourceReference(
MessagePanel.class, "ERROR.gif");
/** reference to SUCCESS image */
static final ResourceReference SUCCESS_IMAGE = new ResourceReference(
MessagePanel.class, "SUCCESS.gif");
/** reference to DENIED image */
static final ResourceReference DENIED_IMAGE = new ResourceReference(
MessagePanel.class, "DENIED.gif");
/*
* (non-Javadoc)
*
* @see
* org.apache.wicket.markup.html.IHeaderContributor#renderHead(org.apache
* .wicket.markup.html.IHeaderResponse)
*/
public void renderHead(IHeaderResponse response) {
response.renderCSSReference(CSS);
}
public MessagePanel(String id, Message message) {
this(id, message, false);
}
public MessagePanel(String id, Message message, boolean hideTitle) {
super(id);
TitlePanel titlePanel = new TitlePanel("titlePanel", new ResourceModel(
message.getTitleKey(), message.getBodyKey()));
add(new Image("logo", message.getMessageType().getImage()));
add(titlePanel);
add(new Label("body", new ResourceModel(message.getBodyKey(), message
.getBodyKey())));
add(new Label("footer", new ResourceModel(message.getFooterKey(), "")));
add(new ListView
private static final long serialVersionUID = 3339539327149648078L;
@Override
protected void populateItem(ListItem
final MessageButton button = item.getModelObject();
item.add(button);
}
});
if (hideTitle) {
titlePanel.setVisible(false);
}
}
void setModal(ConfirmMessageModal modal) {
this.modal = modal;
}
ConfirmMessageModal getModal() {
return this.modal;
}
private class TitlePanel extends Panel {
private static final long serialVersionUID = -1766112576379965369L;
public TitlePanel(String id, IModel
super(id, model);
add(new Label("title", model));
}
}
}
Yukarıda gördüğümüz gibi MessagePanel sınıfı IHeaderContributor arayüzünü gerçekleştirmiş. Eğer bir Wicket Bileşen’inin Header’da değişiklik yapmasını istiyorsak bu arayüzün renderHead() yordamını gerçekleştirmesini sağlamalıyız. CSS ve resim dosyalarının MessagePanel ile paketlemek istediğimiz için aynı dizinde bulunmalıdırlar. Wicket tarafından kullanılabilir olmaları için herbirine ait ResourceReference nesnesi oluşturuyoruz.
Mesaj kutusunun inşaası yapılandırıcı içerisinde gerçekleşmekte. Yapılandırıcı dışında onBeforeRender() yordamı içerisinde de bunu gerçekleştirebiliriz.
Yapılandırıcı içerisinde liste içerisindeki MessageButton’ları göstermek için ListView Wicket yapısını kullanıyoruz. Bu yapı da bir wicket html tanımına ihtiyaç duymaktadır.
<input type="button" wicket:id="button"/>
</div>
Önceki paragraflarda title’in isteğimize göre görünmesini/görünmemesini bunu ayrı bir Wicket Panel gibi düşünerek sağlayabiliriz demiştik. Yapılandırı içerisindeki son satırlarda göndermiş olduğumuz hideTitle parametresine göre panelin setVisible(false) yordamını çağırıyoruz. Başlığı içerecek kısmı panel olarak tanımladığımız için buna ait Wicket Panel sınıfı ve html dosyası oluşturmamız gerekmektedir. Encapsulation prensiplerine uyarak bu panel sınıf tanımını private erişim belirtecine sahip Inner Class olarak yapalım.
...
private class TitlePanel extends Panel {
...
public TitlePanel(String id, IModel
super(id, model);
add(new Label("title", model));
}
}
}
Wicket Html tanımı ise ConfirmMessagePanel$TitlePanel.html dosyası içerisinde bulunmalı. Dikkat edildiği gibi derleme sonrasında oluşacak inner class dosya ismi ile aynı.
<strong style="color: #007087;"><span wicket:id="title">[title]</span></strong>
<br />
</wicket:panel>
Oluşak olan uygulama dizin yapısı aşağıdaki gibidir:
Uygulama içerisinde MessagePanel’imizi nasıl kullanacağız? İşte burada bir örnek mevcut:
Message message = new Message(MessageType.INFO,
"message.panel.title",
"message.panel.body",
"message.panel.footer");
message.addButton(new MessageButton("message.button.no"){
...
@Override
public void clickButton(AjaxRequestTarget target) {
// DO NOTHING
}
});
message.addButton(new MessageButton("message.button.yes"){
...
@Override
public void clickButton(AjaxRequestTarget target) {
// DO NOTHING
}
});
MessagePanel messagePanel = new MessagePanel("content", message);
add(messagePanel);
...
Sonuç :
Mesajlarımızın ModalBox içerisinde görünmesini istiyorsak
Apache Wicket ile modal pencereleri yapmak çok kolay. ModalWindow Wicket yapısından yeni yapılar türeterek bunu gerçekleştirebiliriz.
MessagePanel nesnesini Modal özelliği katmak için sarmalayıcı bir sınıf oluşturalım. MessageModal, ModalWindow’dan türeyen bir yapı.
public MessageModal(String id, Message message) {
super(id);
this.setMinimalHeight(176);
this.setInitialHeight(176);
MessagePanel panel = new MessagePanel(this.getContentId(), message, true);
panel.setModal(this);
this.setTitle(new ResourceModel(message.getTitleKey()));
setContent(panel);
}
public void showMessage(AjaxRequestTarget target) {
this.show(target);
}
}
MessageModal ile gösterilen mesajlarda başlıklar pencerenin başlığı olarak görünmesini istedim. Bunun için MessagePanel’in yapılandırıcısına hideTitle parametresi için TRUE değeri gönderdim, ModalWindow’dan miras aldığım setTitle() ile ModalWindow’a başlık ataması yaptım.
ModalWindow’u göstermek için show() yordamını kullanıyoruz. Bunun için Ajax desteği olan bir bileşenin oluşturduğu istek ile AjaxRequestTarget nesnesi gelmesi gerekmektedir.
MessageModal’ın bir de HTML dosyası olmalı :
<div wicket:id="content"/>
</wicket:panel>
Modal kullanımları için ilgili modal kodlarını içerecek bir Wicket Bileşeni tanımlamamız gerekmektedir.
MessagePanel oluşturur gibi MessageModal oluşturabiliriz:
"message.modal.title",
"message.modal.body",
"message.modal.footer");
message.addButton(new MessageButton("message.button.no"){
@Override
public void clickButton(AjaxRequestTarget target) {
// DO NOTHING
}
});
message.addButton(new MessageButton("message.button.yes"){
@Override
public void clickButton(AjaxRequestTarget target) {
// DO NOTHING
}
});
MessageModal messageModal = new MessageModal("modal", message);
Göstermek için ise bir Ajax olayına ihtiyacımız var. Bunun için bir önceki bölümde oluşturduğumuz MessagePanel nesnesine “Show” isimli yeni bir buton ekliyorum.
@Override
public void clickButton(AjaxRequestTarget target) {
modal.showMessage(target);
}
});
Uygulamayı çalıştırıp sonucunu görelim:
Proje kodlarına buradan ulaşabilirsiniz.
taner.diler[et]gmail.com
CETURK olarak Çankaya Üniversitesi Uygulamalı Matematik Bilgisayar Bilimleri Topluluğu ile birlikte “JAVA ve Kariyer Günü” etkinliği düzenliyoruz. Etkinlik konusu dahilinde JAVA dünyasındaki kariyer olanaklarından bahsedilecek ve etkinlik sonundaki panelimiz ile bilgi alışverişi gerçekleştirilecektir.
Etkinliğe katılım her zamanki gibi ücretsizdir.Bu etkinliği sitesinde duyuran 2 kişiye kitap hediye edilecektir.
Konuşmacılar ve Seminer Konuları:
Kadir Teke – Mehmet Gursul : İş İlanlarında Java
Kenan Sevindik : Java, Kariyer ve Gelecek
Mert Çalışkan : Fikrim Açık, Kodum Açık
Ümit Vardar : JavaFX
Adres:
Çankaya Üniversitesi – Mavi Salon
Tarih: 19 Şubat 2010
Saat: 10:30 – 17:00
- Dependency Injection : Bağımlılıktan kurtulmak için bağımlılığı şırınga etmece
- Google guice : Dependecy Injection yapmanıza olanak veren sağlam bir araç
- Warp - persist : google guice ile veritabanı işlemlerini (transaction gibi) gerçekleştirmek için gerekli olan kütüphane
- Wicket : Kral
- maven biliyor olmanız şart (fazla birşey değil, gözünüz korkmasın lütfen). Eğer bilmiyorsanız bu adresden okuyunuz.
- Bir konsol açın. windows kullananlar cmd ile
- Örnek uygulamayı kendi bilgisayarınıza indiriniz, şöyle ki : svn checkout http://jtpd.googlecode.com/svn/trunk/googleguice_warp_wicket_proje
- 8080 portunun boş olduğundan emin olun - Bu en sık yaptığım hatadır aman siz aynı hataya düşmeyin
- Sonra : mvn jetty:run , deyiniz.
- Az kaldı; şimdi tarayıcıyınızı açarak : http://localhost:8080/google_guice_warp_wicket/ dediğinizde uygulamanın çalışıyor olmazı lazım !
- Eğer com.wideplay warp-persist bulunamadı şeklinde bir hata alırsanız. O zaman http://www.wideplay.com/guicewebextensions2 adresine gidip, buradaki jar dosyasını bilgisayarınıza indiriniz ve aşağıdaki komut ile local repository alanınıza bu wideplay-warp kütüphanesini ekleyeniz.> mvn install:install-file -Dfile="C:\ASF\warp-persist\warp-persist-2.0-SNAPSHOT.jar" -DgroupId=com.wideplay-DartifactId=warp-persist -Dversion=2.0 -Dpackaging=jar
C:\ASF\warp-persist\warp-persist-2.0-SNAPSHOT.jar yerine siz jar dosyasını hangi dizine koymuşsanız onu belirtiniz.
Dependency Injection kavramı
- EventDaoHibernateImp() sınıfı ile doğrudan iletişim kurmuş oldunuz ve EventPage sınıfı ile EventDaoHibernateImp() sınıfı ile arasında çok sıcak ve sıkı bağlar/ bağımlılıklar oluştu. Öyle ki, ileride EventPage sınıfındaki herhangi bir hata veya yenilik EventDaoHibernateImp() sınıfını aynı şekilde EventDaoHibernateImp() sınıfındaki her hata ve yenilik EventPage sınıfını doğruda yani birinci elden ilgilendirir oldu. Tatsız değil mi ?
- EventDaoHibernateImp() sınıfı daha üst seviye bir sınıfdır çünkü veritabanı işlemleri ile ilgilenir ve hayatta ki ne amacı budur. Böyle bir sınıfı gidip de Apache Wicket sayfasının içerisinden direk çağırmak, işlerin hepsini görüntüleme katmanında - view layer - yaptığınız anlamına gelir. Kısaca tüm iş mantığı ön yüz sınıflarında yönetilmeye başlar -ki bu ileride anlamsız derecede acı verici olabilir.
- Kontrol üst seviye bir bileşenden (sınıfdan) - alt seviye bir bileşene (sınıfa) verilmiştir. Bu da tatsız.
- Kısacası üst seviye bir bileşeni (sınıfı), alt seviye bir bileşen içerisinden doğrudan ama doğrudan (new anahtar kelimesi ile) çağırmanız Dependency Injection prensibine aykırıdır.
Google guice (juice diye okuyunuz) : Dependecy Injection yapmanıza olanak veren sağlam bir araç
Warp :: Persist
Wicket
Uygulamanın detayları
- warp-persist : Web oturumuna göre veritabanı bağlantılarını yönetebilmesi için. Bu büyük performans artışlarına sebebiyet veren güzel bir davranıştır.
- Wicket : Apache Wicket, tüm isteklere (request) bakması için vekil tayin ettik.
Hasan Ceylan (http://tr.linkedin.com/in/hasanceylan) tarafından yazılan yazının devamı için buraya gidebilirsiniz.
[--split--]
Nedir bu genel tipler (Generic Types)? Beynimizi çok yormaya gerek yok. Java 1.5 öncesinde bir liste oluşturduğumuzda ve bu listeden bir nesne almak istediğimizde zahmetli bir işe kalkışırdık :
1: List liste = new ArrayList();
2: liste.add(new Integer(0));
3: liste.add(new Integer(1));
4: for(int i=0; i<liste.size(); i++){
5: Integer sayi = (Integer) liste.get(i);
6: }
6. satırda olduğu gibi istediğimiz tipe dönüşüm yaparak (upcasting / downcasting) istediğimiz nesneyi kullanabilirdik.
1: List liste = new ArrayList();
2: liste.add(new Integer(0));
3: liste.add(new Integer(1));
4: liste.add(new String("test"));
5: for(int i=0; i<liste.size(); i++){
6: Integer sayi = (Integer) liste.get(i);
7: System.out.println("["+i+"] = "+ sayi);
8: }
Sonuç:
[0] = 0
[1] = 1
Exception in thread "main" java.lang.ClassCastException: java.lang.String
at com.articles.generics.objectcaching.ObjectPoolManager.main(ObjectPoolManager.java:67)
Oluşturduğumuz liste nin sadece Integer tipindeki nesneleri içereceğini düşünürken takım arkadaşımız başka bir yordam içerisinde öyle bir kod yazmışki bu liste içerisine String tipinde bir nesne atmış ( 4. satır ). Çalışma zamanında (Runtime) bu liste içerisindeki nesneleri Integer tipine dönüştürerek alırken String tipinde bir nesnenin gelmesi hata fırlamasına ve uygulamamızın durmasına neden olmaktadır.
Java 1.5 ile gelen genel tipler ( Generics ) bize tam burada yardımımıza koşmaktadır : çok sık kullandığımız Collection ve Map hiyerarşisindeki torbaların (containers) kullanımında yukarıdaki sorunların ortadan kalkması...
1: List<Integer> intList = new ArrayList<Integer>();
2: intList.add(new Integer(1));
3: intList.add(new Integer(2));
4: intList.add(new String("3"));
Satırları javac ile derlemeye çalıştığımızda :
şeklinde derleme uyarısı alırız. Çünkü 1. satırda <Integer> ifadesi (tip parametresi) ile oluşturacağımız listeye Integer tipi üzerinde işlem gerçekleştireceğimizi söyleriz. String tipinde bir nesneyi listeye koymak istediğimizde ise derleme hatası alırız. Böylece çalışma zamanında (Runtime) beklenmedik tip dönüşümlerinden meydana gelen hatalardan kurtulmuş oluruz.
Nesne Havuzu ( Object Pool )
Jenerik yapıları anlamak için gelin bir uygulama geliştirelim. Bu uygulama veritabanı bağlantı havuzu (DB Connection Pool) yada iş parçacıkları havuzu (Thread Pooling) gibi asıl amacı sürekli tekrarlayan işlemlerde belli bir tipteki nesnelerin her seferde oluşturulması ve silinmesini engellemektir. Böylece uygulamada gereksiz yavaşlamaları engelleyebilir ve nesne takibini iyileştirebiliriz.
Gelin öncelikle uygulamamızı süper yapıları tanımlayarak başlayalım. Bu süper yapılar : arayüzler (interface), süper sınıflar (super class) ve soyut sınıflar (abstract class) olabilir.
Süper yapılara üzerinden uygulamamızı geliştirdiğimiz zaman ileriye yönelik geliştirme ve sistemler arası iletişim daha kolay yapılmış olacaktır.
Oluşturacağımız süper yapılar:
1. Yedeklenebilir Arayüzü (Interface) : Sistem tarafından havuzda tutalacak olan nesnelerin sınıf tanımlamaları bu arayüzü gerçekleştirmelidir.
2. Havuz Arayüzü (Interface) : doldur(), cek()/koy(), bos() soyut yordamlarını içeren arayüzdür. Bu arayüzü gerçekleştiren sınıflar <<Yedeklenebilir>> arayüzünü gerçekleştirmiş yapılar için sınırlandırılmalıdır.
3. HavuzYöneticisi Arayüzü (Interface) : nesneCek(), nesneKoy() ve havuzuKontrolEt() yordamlarını içermektedir.
a. nesneCek() yordamı istenen nesnenin tipine göre ilgili havuzdan nesne çekecek
b. nesneKoy() yordami gönderilen nesneyi, nesnenin tipine göre ilgili havuza geri koyar.
c. havuzuKontrolEt() yordami nesneCek() yordami çağrıldığında ilgili nesne için havuz nesnesinin yaratılıp içerisinin doldurulmasını kontrol eder.
Havuz Arayüzü
/**
*{@link Yedeklenebilir}arayüzünügerçekleştirmiş
*nesneleriçinhavuzgörevinigörür.
*
*@param<T extends YedeklenebilirNesne>
*/
public interface Havuz <T extends Yedeklenebilir> {
/**
*Havuzdannesneçeker.
*@returnT
*/
T cek();
/**
*Nesneyigerikoyar.
*@paramobject
*/
void koy(T nesne);
/**
*clazztipindenesneleriyaratipkendisinidoldurur.
*@paramclazz
*@throwsNesneYaratmaHatasi
*/
void doldur(Class<T> clazz) throws NesneYaratmaHatasi;
/**
*clazztipindenesnelerdenbelirtilenadetkadar
* yaratipkendisinidoldurur.
*@paramclazz
*@paramadet
*@throwsNesneYaratmaHatasi
*/
void doldur(Class<T> clazz, int adet) throws NesneYaratmaHatasi;
/**
*Havuzunbosolupolmadigikontroledilir
*@returnboolean
*/
boolean bos();
}
Havuz arayüzüne ait yukarıdaki tanımlamada dikkatimizi <T extends Yedeklenebilir> tip parametresi çekmektedir. Böylece Havuz arayüzünü sadece Yedeklenebilir arayüzüne erişmiş yapılar için genelleştirmiş / sınırlandırmış (bounding) olduk.
[--split--]
NesneHavuzu Sınıfı
public class NesneHavuzu<T extends Yedeklenebilir>
implements Havuz<T> {
private Vector<T> havuz = new Vector<T>();
/* (non-Javadoc)
* @see com.articles.generics.objectcaching.Havuz#doldur(java.lang.Class)
*/
public void doldur(Class<T> clazz) throws NesneYaratmaHatasi {
this.doldur(clazz, 5);
}
/* (non-Javadoc)
* @see com.articles.generics.objectcaching.Havuz#doldur(java.lang.Class, int)
*/
public void doldur(Class<T> clazz, int adet)
throws NesneYaratmaHatasi {
try {
for(int sayac=0; sayac<adet; sayac++){
this.havuz.add(clazz.newInstance());
}
} catch (InstantiationException e) {
NesneYaratmaHatasi ex =
new NesneYaratmaHatasi(clazz, e.getStackTrace());
throw ex;
} catch (IllegalAccessException e) {
NesneYaratmaHatasi ex =
new NesneYaratmaHatasi(clazz, e.getStackTrace());
throw ex;
}
}
/*
* (non-Javadoc)
*
* @see com.articles.generics.objectcaching.Pool#pull()
*/
public T cek() {
T object = havuz.remove(0);
return object;
}
/*
* (non-Javadoc)
*
* @see com.articles.generics.objectcaching.Pool#push(com.articles.generics.objectcaching.CachableObject)
*/
public void koy(T object) {
havuz.add(object);
}
/* (non-Javadoc)
* @see com.articles.generics.objectcaching.Havuz#bos()
*/
public boolean bos() {
return this.havuz.isEmpty();
}}
NesneHavuzu sınıfına dikkat edersek : Havuz arayüzündeki tip parametresi
<T extends Yedeklenebilir> burada da mevcut. Neden böyle? Bakalım:
NesneHavuzu sınıfında <T extends Object> tanımını kullanıp derlemek istediğimizde :
şeklinde bir uyarı ile karşılaşırdık. Bu uyarıda NesneHavuzu sınıfı tanımlamasındaki tip parametresi, Havuz arayüzünün beklediği tip parametresinin sınırları dışında oluduğu belirtilmektedir.
NesneHavuzu sınıfında <T extends X_Nesne> tanımını kullanıp derlemek istediğimizde herhangi sorun ile karşılaşmayız çünkü T tip parametresi Havuz arayüzünün beklediği sınırlar yani Yedeklenebilir arayüzünün alt hiyerarşisi içerisindedir.
Peki Havuz arayüzünün tanılamasını public interface Havuz <T> şeklinde değiştirdiğimiz de ne olur? Birşey olmaz çünkü böyle yaparak Havuz arayüzü üzerindeki kısıtlamayı kaldırıp bu arayüzü her tipten yapı için çalışır duruma getirmiş oluruz, standart Java paketi içerisindeki torba (Hash, List ...) yapılarında olduğu gibi.
Şimdi de şöyle bişey deneyelim. Havuz arayüzünü eski haline getirelim ama bu sefer NesneHavuzu sınıfı tanımını NesneHavuzu<T> implements Havuz<T> şeklinde değiştirelim. Derlemek istediğimiz de
<T extends Object> örneğimizde olduğu gibi yine aynı nedenden dolayı derleme zamanında uyarı alırız.
Peki alt hiyerarşi sınırlandırması için bir tanımlama mevcutken üst hiyerarşi sınırlandırması için bir tanımlama mevcut mu? <T super Yedeklenebilir> Yedeklenebilir arayüzünün üst hiyerarşisi için sınırlama yapılır.
Şimdiye kadar yazmış olduğumuz yapıların testini gerçekleştirelim.
public class HavuzTest extends TestCase {
private X_Nesne x_n1 = new X_Nesne();
private X_Nesne x_n2 = new X_Nesne();
private Y_Nesne y_n1 = new Y_Nesne();
private Y_Nesne y_n2 = new Y_Nesne();
Object obje_1 = new Object();
private NesneHavuzu<X_Nesne> x_havuz = new NesneHavuzu<X_Nesne>();
private NesneHavuzu<Y_Nesne> y_havuz = new NesneHavuzu<Y_Nesne>();
private NesneHavuzu<Yedeklenebilir> genel_havuz = new NesneHavuzu<Yedeklenebilir>();
public void testCek() {
X_Nesne x_nesne_1 = x_havuz.cek();
// Y_Nesne x_nesne_2 = x_havuz.cek(); Derleme hatasi verir
Y_Nesne y_nesne_1 = y_havuz.cek();
// Cek yordami Yedeklenebilir tipinde değer dönerken
// biz X_Nesne tipinde bekliyoruz.
// X_Nesne x_nesne_3 = genel_havuz.cek();
X_Nesne x_nesne_3 = (X_Nesne) genel_havuz.cek();
}
public void testKoy() {
x_havuz.koy(x_n1);
x_havuz.koy(x_n2);
// x_havuz.koy(y_n1); Derleme hatasi verir
y_havuz.koy(y_n1);
y_havuz.koy(y_n2);
genel_havuz.koy(x_n1);
genel_havuz.koy(y_n1);
// x_havuz.koy(obje_1); DERLEME HATASI
// y_havuz.koy(obje_1); DERLEME HATASI
// genel_havuz.koy(obje_1); DERLEME HATASI
}
}
HavuzYoneticisi Arayüzü
public interface HavuzYoneticisi {
<T extends Yedeklenebilir> void nesneKoy(T nesne) throws NesneYaratmaHatasi;
<T extends Yedeklenebilir> T nesneCek(Class<T> clazz) throws NesneYaratmaHatasi;
<T extends Yedeklenebilir> void havuzuKontrolEt(Class<T> clazz) throws NesneYaratmaHatasi;
}
Burada dikkat etmemiz gereken, arayüzü değil arayüz içerisindeki yordamları genelleştiriyor olmamız. <T extends Yedeklenebilir> tip parametresi korunarak yine hiyerarşi sınırlandırması yapmış oluyoruz. Eğer HavuzYoneticisi arayüzünü de <T extends Yedeklenebilir> tip parametresi ile genelleştirmiş olsaydık sadece tek tip bir yapı için çalışıyor hale gelirdi. Tıpkı Havuz arayüzü gibi :
NesneHavuzu<X_Nesne> x_havuz = new NesneHavuzu<X_Nesne>();
NesneHavuzuYoneticisi Sınıfı
public class NesneHavuzuYoneticisi implements HavuzYoneticisi {
private Map<Class<? extends Yedeklenebilir>,
Havuz<? extends Yedeklenebilir>>
havuzMap = new HashMap<
Class<? extends
- Natali Yeşilbahar (http://www.xing.com/ Türkiye İş Geliştirme ve Satış Müdürü)
- Emre Sokullu (grou.ps kurucusu)
"Scalability @ Grou.ps" sunumuna buradan ulaşabilirsiniz.
Bahadır Ödevci'nin SOE or SOA or SOI or EAI, Which migration path to chose ? konusunu bizlere sundu. Özellikle bankacılık sektöründe yoğun olarak kullanılan bu teknolojilerin artı ve eksi yanlarını ve hangi durumda hangi teknolojiyi seçmeliyiz sorularını cevaplandıran Bahadır Ödevci'ye bir kez daha teşekkür ederiz.

Misyon - Ülkü (mission) : Bu şirketin var oluş amacını belirler. Şirket sadece para kazanmak için var olmuş ise bu şirket büyük ihtimalle çökecektir. örnek misyonlar :
- Her eve bilgisayar girecek - Microsoft
- Araba herkesin alabileceği kadar ucuz olmalı ve biz herkese araba satacağız- Henry Ford - Ford
Takım (team): İyi bir ekip ve ekip çalışması olmaz ise, şirketin devamı söz konusu olamaz. Takım oyunu başarı için şarttır. Şirket için görev tanımları kesin ve net olmalıdır. Kim genel müdür, kim kodcu, kim pazarlamacı, kim devlet vergi işlerinden sorumlu ?
Leadership (liderlik): Bu ekibin başında bir lider olması gerekir. Lidersiz bir işletme, yönünü her an kaybedebilir. Bu da şirketin devamını tehlikeye atabilir.
Bu üç ana maddeye özetle değindik sonra üçgenin iç kısımlarını sırayla incelersek.
CashFlow (NakitAkışı == finansal planlama ve muhasebe) : Yeni başlayan şirketler bir çoğu bu kısmı iyi bir şekilde yönetememektedirler. Bunun sonucu olarak şirket maddi olarak zora girmekte ve çöküş gerçekleşmektedir. Bu noktada finansal planlama da işin büyükçe bir kısmını oluşturmadır. Bu üçgenin en temel kısmını oluşturduğundan eğer bu kısımda bir aksaklık oluşursa, şirketin geri kalan kısmının ayakta kalabilmesi çok güçtür.
İletişim ve pazarlama (comminication) : Firmanın iyi bir iletişim alt yapısı ve pazarlama kollarının olması gerekir. Satış yapabildiğiniz sürece varsınız (sanırım mühendislerin uyuz olduğu bir cümle ya da en azından bana öyle geliyor ama ne yazik ki doğru ...)
Sistemler (Systems) : "Şirketin işleyişinin sistemlere bağlanması, kişilere değil" prensibini esas almamız gereken katman, işlerin büyümesi esnasında son derece önemlidir. Bu nokta işlerin büyümesi için önemli zira McDonalds hep bu katmanda örnek gösterilen şirkettir. En vasıfsız kişilerle bile işleri yürüten bir sistem !!! . Kısacası şirketin başarılı ve büyümesi için birçok sisteme ihtiyaç var. Aklıma gelenler :
- Muhasebe kontrol ve takibi için bir düzen / sistem
- Proje geliştirme sistemleri : Agile süreçler veya bir başkası
- Hudson sistemim var mı (https://hudson.dev.java.net/) ?
- Kod versiyonlama sistemi var mı ?
- Hata yakalama ve ayıklama sistemi
- Her hafta uygulama geliştiriciler arasında sistemli toplantılar.
- JSF yerine Apache Wicket kullanılması (Bu kısım tamamen şahsi fikrimdir, JSF kullananlar lütfen alınmasın :P )
- ...
Resmi hususlar (Legal) : Anlaşmalar, patent ve telif hakları konuları dikkatli bir şekilde takip edilmelidir yoksa oyun başlamadan biter
.
Ürün (Product) : Elbette şirketin sunacağı muhteşem bir ürün olmalıdır.
Dikkat ediniz! Ürün bu üçgenin en ufak kısmını oluşturuyor. Ben bu üçgeni görmeden evvel hep ürene odaklanmıştım. Ürüne şu özelliği de koysak muhteşem olurdu veya şu özelliği çıkartsak mı ? Bu tür sorularda bir tuhaflık yok, sorulmalı da fakat bunun yanında bir çok soru daha sorulmalı ve cevapları olmalı. İşte o sorulardan aklıma gelenler : Yasal vergi oranları ne kadar ? Stopaj nedir ? Muhasebe bilgim nasıl ? Nakit akış planım var mı ? Pazarlama ve satış konusunda ne yapmalım ? Takımım iyi mi ? Ben iyi bir lider miyim ? Misyonumuz nedir ? iyi bir avukatım var mı ? Ben bu şirketi neden açtım deli mıyım ? :) ... .....
İşe başlarken ve yürütüken sadece ürüne (bu kısım için yazılım da diyebiliriz) odaklanırsa, sonuçları felaket olabilir, aman dikkat.
Altuğ Bilgin ALTINTAŞ
altug - at - kodcu.com
Taner Diler
taner.diler@gmail.com
İzleyeceğimiz adımlar:
2. Pom.xml'in oluşturulması, Spring Container'i için gerekli paket bağımlılık ayarlarının yapılması
3. Spring application-context.xml'in oluşturulması ve basit bir uygulama ile injection yönetiminin test edilmesi
4. Hibernate paket bağımlılık ayarlarının yapılması ve Hibernate konfigurasyonunun gerçekleştirilmesi
5. Wicket için pom.xml üzerinde paket bağımlılık ayarlarının yapılması
6. Spring application-context.xml ve web.xml de Spring ve Wicket ayarlarının yapılması
Maven kurulumu için maven.apache.org sitesinden maven paketini indirip açtıktan sonra içerisindeki bin klasörününü de sistemin “Ortam Değişkenleri”ne tanımlayabilirsiniz.
mvn archetype:create -DgroupId=org.jtpd
-DartifactId=maven_spring_hibernate_wicket
-DpackageName=org.jtpd
komutunu kullanarak maven projemizi oluşturalım. Pom.xml içerisindeki packaging tanımını war yapalım.
Oluşan pom.xml :
| <'project ...> <'modelVersion>4.0.0<'/modelVersion> <'groupId>org.jtpd<'/groupId> <'artifactId>maven_spring_hibernate_wicket<'/artifactId> <'packaging>war<'/packaging> <'version>1.0-SNAPSHOT<'/version> <'name>maven_spring_hibernate_wicket<'/name> <'url>http://maven.apache.org<'/url> <'dependencies> <'dependency> <'groupId>junit<'/groupId> <'artifactId>junit<'/artifactId> <'version>3.8.1<'/version> <'scope>test<'/scope> <'/dependency> <'dependency> <'groupId>org.slf4j<'/groupId> <'artifactId>slf4j-jdk14<'/artifactId> <'version>1.4.2<'/version> <'/dependency> <'/dependencies> <'/project> |
Oluşan dizin yapısı:
Log4j, Spring gibi konfigurasyon dosyalarını koymak için /src/main/resources dizinini ve web dosyalarını koymak için /src/main/webapp oluşturalım. Ve sonrasında pom.xml'i açıp aşağıdaki ayarlamaları yapalım.
| <'build> <'resources> <'resource> <'directory>src/main/resources<'/directory> <'filtering>true<'/filtering> <'/resource> <'/resources> <'plugins> <'plugin> <'groupId>org.apache.maven.plugins<'/groupId> <'artifactId>maven-compiler-plugin<'/artifactId> <'version>2.0.2<'/version> <'configuration> <'source>1.5<'/source> <'target>1.5<'/target> <'/configuration> <'/plugin> <'/plugins> <'/build> |
Gelin şimdi Spring & Hibernate paket bağımlılıklarını ayarlayalım:
| <'dependencies> ... <'!-- SPRING DEPENDENCIES --> <'dependency> <'groupId>org.springframework<'/groupId> <'artifactId>spring<'/artifactId> <'version>${spring.version}<'/version> <'/dependency> <'dependency> <'groupId>org.springframework<'/groupId> <'artifactId>spring-web<'/artifactId> <'version>${spring.version}<'/version> <'/dependency> <'dependency> <'groupId>org.springframework<'/groupId> <'artifactId>spring-aspects<'/artifactId> <'version>${spring.version}<'/version> <'/dependency> <'!-- HIBERNATE DEPENDENCIES --> <'dependency> <'groupId>mysql<'/groupId> <'artifactId>mysql-connector-java<'/artifactId> <'version>5.1.6<'/version> <'/dependency> <'dependency> <'groupId>javax.persistence<'/groupId> <'artifactId>persistence-api<'/artifactId> <'version>1.0<'/version> <'scope>provided<'/scope> <'/dependency> <'dependency> <'groupId>org.hibernate<'/groupId> <'artifactId>hibernate-annotations<'/artifactId> <'version>3.4.0.GA<'/version> <'/dependency> <'dependency> <'groupId>org.hibernate<'/groupId> <'artifactId>hibernate-entitymanager<'/artifactId> <'version>3.4.0.GA<'/version> <'/dependency> ... <'/dependencies> <'properties> <'spring.version>2.5.6<'/spring.version> <'/properties> |
Spring konfigurasyonunu gerçekleştirelim. Bunun için src/main/resources altında application-context.xml dosyasını oluşturalım.
| <'?xml version="1.0" encoding="UTF-8"?> <'beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd" > <'context:annotation-config /> <'context:component-scan base-package="org.jtpd" /> <'aop:aspectj-autoproxy /> <'tx:annotation-driven /> <'bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <'property name="dataSource" ref="dataSource" /> <'property name="annotatedClasses"> <'list> <'value>org.jtpd.core.User<'/value> <'value>...<'/value> <'/list> <'/property> <'property name="hibernateProperties"> <'props> <'prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect<'/prop> <'prop key="hibernate.show_sql">true<'/prop> <'/props> <'/property> <'/bean> <'bean id="dataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" destroy-method="close"> <'property name="url" value="jdbc:mysql://db.jtpd.org:3306/jtpd" /> <'property name="user" value="root" /> <'property name="password" value="****" /> <'/bean> <'bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <'property name="sessionFactory" ref="sessionFactory"/> <'property name="dataSource" ref="dataSource"/> <'/bean> <'/beans> |
Yukarıdaki konfigurasyonda, spring injectionlarının ve transaction tanımlarının annotationlar üzerinden yapılacağı belirtilir.
Uygulama içerisindeki kullanımı :
| @Entity @Table(name=”User”) public class User { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; ... } @Repository //Spring Annotation @Transactional public abstract GenericDAO<'T> { @Autowired //Spring Annotation private SessionFactory sessionFactory; public Session getSession(){ return sessionFactory.openSession(); } public void save(T entity){ getSession().save(entity); } } @Repository //Spring Annotation @Transactional public class UserDAO extends GenericDAO<'User> { ... } @Service //Spring Annotation @Transactional public UserService { @Autowired //Spring Annotation private IuserDAO userDAO; //Ornek public void save(User user){ // Transaction Yönetimi spring tarafindan yapilmakta userDAO.save(user); } } |
Şu ana kadar yazmış olduğumuz kod örneğini ve konfigurasyonu test etmek için standalone çalışabilecek bir kod çalışması yapalım. Öncelikle pom.xml içerisinde aşağıdaki konfigurasyonu yapalım.
| <'build> <'plugins> ... <'plugin> <'groupId>org.codehaus.mojo<'/groupId> <'artifactId>exec-maven-plugin<'/artifactId> <'executions> <'execution> <'phase>package<'/phase> <'goals> <'goal>java<'/goal> <'/goals> <'/execution> <'/executions> <'configuration> <'mainClass>org.jtpd.App<'/mainClass> <'/configuration> <'/plugin> ... <'/plugins> <'/build> |
org.jtpd.App java dosyasını oluşturalım:
| package org.jtpd; import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; public class App { public static void main(String[] args) { try { ApplicationContext factory = new FileSystemXmlApplicationContext( "targetclassesapplication-context.xml"); IUserService userService = (IUserService) factory .getBean("userService"); userService.save(new User()); } catch (Exception e) { e.printStackTrace(); } } } |
App sınıfını komut satırından
| mvn exec:java |
komutu ile çalıştırabiliriz.
Herşey istediğimiz gibi ise şimdi geliştirdiğimiz yapıyı web uygulaması haline getirelim. Bunun için pom.xml'de :
| <'dependencies> ... <'dependency> <'groupId>org.apache.wicket<'/groupId> <'artifactId>wicket-spring<'/artifactId> <'version>${wicket.version}<'/version> <'/dependency> <'dependency> <'groupId>org.apache.wicket<'/groupId> <'artifactId>wicket<'/artifactId> <'version>${wicket.version}<'/version> <'/dependency> <'dependency> <'groupId>org.apache.wicket<'/groupId> <'artifactId>wicket-extensions<'/artifactId> <'version>${wicket.version}<'/version> <'/dependency> <'/dependencies> ... <'properties> <'wicket.version>1.4.0<'/wicket.version> <'spring.version>2.5.6<'/spring.version> <'/properties> |
src/main/webapp altında WEB-INF/web.xml dosyasını oluşturalım ve aşağıdaki konfigurasyonları tanımlayalım
| <?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>JTPD</display-name> <filter> <filter-name>wicket-spring-hibernate</filter-name> <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class> <init-param> <param-name>applicationFactoryClassName</param-name> <param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value> </init-param> </filter> <filter-mapping> <filter-name>wicket-spring-hibernate</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:application-context.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app> |
Web.xml de Spring ve Wicket çatılarına ait tanımlamaları yaptık.application-context.xml içerisinde de Wicket uygulamasını tanımlamamız gerekiyor. Web.xml içerisinde WicketFilter konfigurasyonunda Wicket çatısına aşağıdaki WebApplication sınıfını hangi factory üzerinden alacağımızı belirtiyoruz. Burada Wicket ile Spring entegrasyonunu gerçekleştirmiş oluyoruz.
| ... <bean id="wicketApplication" class="org.jtpd.web.JTPDWicketApplication" /> ... |
Şu ana kadar Maven, Spring, Hibernate ve Wicket entegrasyonunu bir şekilde gerçekleştirmiş bulunmaktayız. Fakat Wicket bileşenlerinden Spring bean'lerine injection yöntemiyle erişmek için JTPDWicketApplication sınıfının yapılandırıcı yordamlarında
| addComponentInstantiationListener(new SpringComponentInjector(this)); |
çağırımlarını yapmamız gerekmektedir.
JTPDWicketApplication sınıfı :
| package org.jtpd.web.JTPDWicketApplication; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.spring.injection.annot.SpringComponentInjector; /** * Application object for your web application. * <'p/> * If you want to run this application without deploying, run the Start class. */ public class JTPDWicketApplication extends WebApplication { /* (non-Javadoc) * @see org.apache.wicket.protocol.http.WebApplication#init() */ @Override protected void init() { // TODO Auto-generated method stub super.init(); addComponentInstantiationListener(new SpringComponentInjector(this)); } @Override public Class<'Index> getHomePage() { return Index.class; } } |
WebApplication, WebPage gibi Wicket bileşenleri içerisinden Spring bean'lerini kullanabilmek için @SpringBean annotation'ını kullanmamız gerekmektedir. JTPDWebApplication içerisinden çağırılan Index.class yani WebPage'den türeyen Index sınıfını oluşturalım ve buradan userService Spring Bean'ini nasıl çağırdığımızı görelim.
| package org.jtpd.web; /** * @author tdiler * */ import org.apache.wicket.PageParameters; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.spring.injection.annot.SpringBean; import org.jtpd.core.IUserService; import org.jtpd.core.User; /** * Homepage */ public class Index extends WebPage { private static final long serialVersionUID = 1L; @SpringBean IUserService userService; public Index(final PageParameters parameters) { User user = new User(); userService.save(user); add(new Label("label", "Kullanıcı kaydedildi.")); } } |
Wicket çatısında yazılan WebPage, Panel gibi bileşenler için markup tanımlarını içeren sınıf ile aynı isimde *.html uzantılı dosyalar bulunmalıdır. Maven ile derleme ve paket oluşturma sonucunda bu html dosyalarınında değerlendirilmesi için pom.xml’de şu eklemeyi yapacağız:
| <resources> ... <resource> <filtering>false</filtering> <directory>src/main/java</directory> <includes> <'include>**</include> </includes> <excludes> <exclude>**/*.java</exclude> </excludes> </resource> ... </resources> |
İlgili çalışmaya ait kodlara buradan ulaşabilirsiniz.
Tasarım Kalıpları & AntiPatterns & Tasarım Prensipleri
taner.diler@gmail.com

File > New > Project diyoruz.

