You are on page 1of 423

Kurumsal Java

Burak Bayraml

Kurumsal Java c 2005 Burak Bayraml

Bu kitabn t m yayn haklar Burak Bayramlya aittir. Kendisinden izin u alnmadan bu eserden ksmen veya tamamen alnt yaplamaz, hibir ekilde kopya c s edilemez, oaltlamaz ve yaynlanamaz. c g

Editr: Burak Bayraml o Hazrlayan: Burak Bayraml Derleyen: Burak Bayraml

Birinci Basm: 2005 / Istanbul

ISBN: 975-00427-0-0

Vatandalarma s

Kural 1: Teknoloji seerken her zaman en ksa, en hzl ileyecek c s ve kod bakm klfeti en az olacak dili semeliyiz. Ksalk, yazlan u c kodun tuttuu yer ile, bakm klfeti ise kodunuzda bir deiiklik g u gs yapldnda ka baka yerin deimesi gerekecei, kodun okunabilirlii g c s gs g g ve anlalabilirlii ile alkaldr. Sektrmzde, aynen temel bilims g a ou u lerde olduu gibi basitlik, esastr. g Kural 2: Bir proje iin gereklilik kodlarken, ayn projede teknologlar c iin teknoloji uretmemeye dikkat etmeliyiz. Biz, kurumsal programclarn c grevi, iletmeler iin teknoloji uretmektir. Teknoloji amal teknoloji o s c c yazmaktan kanp, amalarmza uyan bir teknoloji bulup onu kulc c lanmalyz. Kural 3: Prensip edinirken, hatrlamas en rahat ve buna oranla etkisi en fazla olacak prensibi edinmeli ve prensibi disiplinle takip etmeliyiz. Kural 4: Insanlar (programclar) unutabilirler ve mekanik hata lar yapabilirler. Insanlardan her anda her ii hatasz yapan biyonik s yaratklar olmalarn beklemeliyiz. En verimli alanlar, biyonik c s adam/kadn olmann imkanszl sebebiyle yapabilecekleri hatalar g o ou ngrp, ona gre kendini koruyucu alkanlklar ve prensipleri edio s nen insanlardr (bkz. Kural #3). Kural 5: Ne zaman ki bir teknolojiyi ayakta tutmak iin kod uretmc eye baladk, Kural #1 nda o teknolojiyi atma zaman gelmitir. s sg s Eer A dilini kullanp B dilini uretiyor ve olduu gibi kullanabiliyg g orsak, A dilinin daha ksa ve basit olduu apak ortadadr. g c Kural 6: Kurumsal kodlarmzda kullanabileceimiz yeni teknolog jiler, her zaman metin bazl yeni diller olarak ortaya karlar. Bu c dillerin ounluu iin grsel IDE beklemek bounadr. Teknolojic g g c o s leri metin bazl olarak kullanmaya almalyz. s Kural 7: Yazdmz kodlarda, komut satrnda ilettiimiz kog s g mutlarda ve yaptmz tklamalarda, tekrarn ve tekerrrn her g uu trlsn ortadan kaldrmalyz. Kurumsal programclkta tekrar, u uu u hamallktr. Hamal ilerini, onu en iyi yapacak eye, bilgisayara s s brakmalyz.

c Iindekiler
c Iindekiler o Onsz 1 Giri s 1.1 Blm Rehberi . . . . . . . . . . . . . . . . . . . . . . . . . ou 1.2 Trke Kullanm . . . . . . . . . . . . . . . . . . . . . . . . u c 1.3 Ek Bilgiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Hibernate 2.1 Faydalar . . . . . . . . . . . . . . . . . . . . . . 2.2 Kurmak . . . . . . . . . . . . . . . . . . . . . . 2.2.1 Balant Havuzlar (Connection Pools) g 2.2.2 Onbellek . . . . . . . . . . . . . . . . . 2.2.3 Ornek Proje Dizin Yaps . . . . . . . 2.2.4 Hibernate Session . . . . . . . . . . . . 2.2.5 Hibernate Transaction . . . . . . . . . 2.3 Kimlik Idaresi . . . . . . . . . . . . . . . . . . . 2.3.1 Birden Fazla Kolon Anahtar Ise . . . . 2.3.2 Anahtar Uretimi . . . . . . . . . . . . 2.4 Drt Ilem . . . . . . . . . . . . . . . . . . . . . o s s 2.5 Nesneler Aras Ilikiler . . . . . . . . . . . . . . s 2.5.1 Bire Bir (One to One) Iliki . . . . . . s 2.5.2 Bire Cok (One to Many) Iliki . . . . . s 2.5.3 Coka Cok (Many to Many) Iliki . . . 2.5.4 Sralanm Set Almak . . . . . . . . . s 2.6 Sorgular . . . . . . . . . . . . . . . . . . . . . . 2.6.1 Basit Bir Sorgu . . . . . . . . . . . . . c 2.6.2 Join Ieren Sorgular . . . . . . . . . . 2.6.3 Sorgular ve Isimli Parametreler . . . . 2.6.4 Guruplama Teknikleri . . . . . . . . . 2.6.5 SQL ile Sorgulamak . . . . . . . . . . v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v xiii 1 3 4 5 7 8 11 13 13 15 16 17 18 19 21 22 23 23 24 27 28 29 30 31 32 32 33

2.7 2.8

2.9

2.6.6 Deiik Nesnelerden Tek Sonu Listesi gs c Otomatik Sema Uretimi . . . . . . . . . . . . . Middlegen . . . . . . . . . . . . . . . . . . . . . 2.8.1 Felse Tavsiye . . . . . . . . . . . . . . 2.8.2 Kullanmak . . . . . . . . . . . . . . . . 2.8.3 Test Sema . . . . . . . . . . . . . . . . Ozet . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33 36 37 37 38 39 41 43 44 45 45 47 48 49 50 50 51 53 54 56 58 58 59 59 62 62 64 64 65 66 69 73 73 74 75 76 77 78 79 79 81 84 90

3 Web Uygulamalar 3.1 MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Ana Kavramlar . . . . . . . . . . . . . . . . . . . . . . . 3.2.1 Form ve Action . . . . . . . . . . . . . . . . . . 3.2.2 JSP ve Form Balantlar . . . . . . . . . . . . g 3.2.3 Actionlardan Sonra Ynlendirme . . . . . . . . o 3.2.4 Action Zincirleme . . . . . . . . . . . . . . . . . 3.2.5 Struts ve JSTL . . . . . . . . . . . . . . . . . . 3.3 Gelitirme Ortam . . . . . . . . . . . . . . . . . . . . . s 3.3.1 Gelitirme Dizinleri . . . . . . . . . . . . . . . . s 3.3.2 Hedef Dizinleri . . . . . . . . . . . . . . . . . . 3.3.3 Web Ayar Dosyalar . . . . . . . . . . . . . . . 3.3.4 HibernateSessionCloseFilter . . . . . . . . . . . 3.3.5 Hzl Gelitirme . . . . . . . . . . . . . . . . . . s 3.4 Trke Karakter Destei . . . . . . . . . . . . . . . . . . u c g 3.4.1 Apache . . . . . . . . . . . . . . . . . . . . . . . 3.4.2 Http Request . . . . . . . . . . . . . . . . . . . 3.4.3 JSP . . . . . . . . . . . . . . . . . . . . . . . . 3.4.4 Struts Resources . . . . . . . . . . . . . . . . . 3.4.5 Hibernate . . . . . . . . . . . . . . . . . . . . . 3.4.6 Veri Taban . . . . . . . . . . . . . . . . . . . . 3.5 Etiketler . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.1 Form Alkal Etiketler . . . . . . . . . . . . . . a s 3.5.2 Prezentasyon ve Ilem Amal Etiketler . . . . . c 3.6 Tiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6.1 Kurmak . . . . . . . . . . . . . . . . . . . . . . 3.6.2 Sablon . . . . . . . . . . . . . . . . . . . . . . . 3.6.3 Sablonda Olaan Deer Tanmlamak . . . . . . g g 3.7 Hata Mesajlar Idaresi . . . . . . . . . . . . . . . . . . . 3.7.1 Parametre Gerektiren Hata Mesajlar . . . . . . 3.7.2 Actionlarda Muamele Grmeyen Hatalar . . . o 3.8 Web Kodlama Kalplar . . . . . . . . . . . . . . . . . . 3.8.1 Tek Nesne Ykle ve Gster . . . . . . . . . . . u o 3.8.2 Nesne Ekle . . . . . . . . . . . . . . . . . . . . 3.8.3 Tek Nesne Ykle ve Deitir . . . . . . . . . . . u gs 3.8.4 Byk Sonu Listelerini Sayfa Sayfa Gstermek u u c o

3.9

3.8.5 Dosya Yklemek (File Upload) . . . . . . . . . . . u 3.8.6 Kullanc Isim ve Sifre Kontrol (Login) . . . . . . u Ozet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

95 97 102 103 104 105 106 109 110 111 113 118 119 120 120 121 125 127 127 129 130 133 133 135 138 140 140 141 143 151 152 154 155 157 157 170 173 182 183 183 185 186

4 Datk Nesneler g 4.1 Neden Orta Katman . . . . . . . . . . . . . . . . . 4.2 Genel Mimari . . . . . . . . . . . . . . . . . . . . . 4.2.1 Command Mimarisi . . . . . . . . . . . . . 4.3 RMI . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 Spring . . . . . . . . . . . . . . . . . . . . 4.3.2 Basit Bir RMI/Spring Ornei . . . . . . . g 4.3.3 RMI ve Command Mimarisi . . . . . . . . 4.4 JNDI . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5 EJB Session Bean . . . . . . . . . . . . . . . . . . . 4.5.1 Sonu Dizin Yaps . . . . . . . . . . . . . c 4.5.2 SFSB ve SLSB . . . . . . . . . . . . . . . 4.5.3 SFSB . . . . . . . . . . . . . . . . . . . . . 4.5.4 EJB ve Command Mimarisi . . . . . . . . 4.6 JMS . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.1 Ana Kavramlar . . . . . . . . . . . . . . . 4.6.2 JBossMQ ile Queue ve Topic Oluturmak s 4.6.3 Listener ile Mesaj Okumak . . . . . . . . 4.6.4 Blok Eden Okuma . . . . . . . . . . . . . 4.6.5 Message Driven Bean Ile Okumak . . . . . 4.6.6 Mesaj Gndermek . . . . . . . . . . . . . o 4.6.7 Filtrelemek . . . . . . . . . . . . . . . . . 4.7 JMS ve Command Mimarisi . . . . . . . . . . . . . 4.7.1 Fiziksel Yap . . . . . . . . . . . . . . . . 4.7.2 Kullanclar Ayrt Etmek . . . . . . . . . 4.7.3 Kodlar . . . . . . . . . . . . . . . . . . . . c 5 Performans, Oleklemek 5.1 Kavramlar . . . . . . . . . . . . . . . . . . . . . . 5.2 Yaklam . . . . . . . . . . . . . . . . . . . . . . . s 5.2.1 Analiz . . . . . . . . . . . . . . . . . . . 5.3 Analiz Aralar . . . . . . . . . . . . . . . . . . . c 5.3.1 JMeter . . . . . . . . . . . . . . . . . . . 5.3.2 Unix Uzerinde Istatistik Toplamak . . . 5.3.3 Detayl Performans Istatistii Toplamak g c 5.4 Performans Iyiletirmeleri ve Oleklemek . . . . . s 5.4.1 JVM . . . . . . . . . . . . . . . . . . . . 5.4.2 Log4J . . . . . . . . . . . . . . . . . . . 5.4.3 JBoss Threadlerini Arttrmak . . . . . . s 5.4.4 Al Hibernate Ilemleri . . . . . . . . c s . . . . . . . . . . . .

5.4.5 5.4.6 5.4.7 5.4.8 5.4.9 5.4.10

Hibernate Onbellek Kullanm . . . . . . . . . . Hibernate ve Tembel Ykleme (Lazy Loading) . u Hibernate Ykleme (Fetching) Stratejileri . . . u c JBoss Kmesi (Web Uygulamalar Iin) . . . . u EJB Kmesi Yaratmak . . . . . . . . . . . . . . u Veri Tabannda Indeks Kullanm . . . . . . . .

. . . . . .

. . . . . .

187 193 194 195 204 210 213 214 215 218 218 220 222 223 228 237 238 239 241 247 251 251 256 257 257 259 261 264 265 265 266 267 272 273 276 276 277

6 Sonu Ortam c 6.1 Kod Gnderimi . . . . . . . . . . . . o 6.1.1 SSH ve SCP . . . . . . . . . s 6.2 Uygulama Ileyiini Kontrol Etmek . s 6.2.1 Blok Eden Servis Scriptleri 6.2.2 Deamon Programlar . . . . 6.3 Uygulamadan Istatistik Almak . . . 6.3.1 JMX ile MBean Yazmak . . 6.3.2 JmxMonitor . . . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

7 Test Etmek 7.1 Birim Testleri . . . . . . . . . . . . . . . . . . . . . . . s 7.1.1 JUnit - Birim Test Iletici . . . . . . . . . . . 7.1.2 Kurumsal Kodlar Birim Testinden Geirmek c 7.1.3 Hibernate Test Altyaps . . . . . . . . . . . . 7.2 Kabul Testleri . . . . . . . . . . . . . . . . . . . . . . . 7.2.1 Otomatik Kabul Testleri . . . . . . . . . . . . 7.3 Ne Kadar Test Gerekli? . . . . . . . . . . . . . . . . . 7.3.1 Birim Test Miktar . . . . . . . . . . . . . . . 7.3.2 Kabul Test Miktar . . . . . . . . . . . . . . . 8 Nesnesel Tasarm 8.1 Nesnesel Tasarm ve Teknoloji . . . . . . 8.2 Modelleme . . . . . . . . . . . . . . . . . 8.2.1 Prensipler . . . . . . . . . . . . 8.2.2 Fonksiyonlarn Yan Etkisi . . . 8.2.3 Veri Taban ve Nesnesel Model 8.2.4 Metotlar ve Alveri Listesi . . s s 8.3 Tasarm Dzenleri . . . . . . . . . . . . u 8.3.1 Kullanlan Dzenler . . . . . . u s 8.3.2 POJOlar ve Ilem Mant . . g 8.3.3 Dier Dzenler . . . . . . . . . g u 8.4 Mimari . . . . . . . . . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

9 Veri Tabanlar s 9.1 Ilikisel Model . . . . . . . . . . . . . . . s 9.1.1 Tablo Aras Ilikiler . . . . . . . 9.1.2 Veri Modelini Normlletirmek a s 9.2 Yardmc Kavramlar . . . . . . . . . . . 9.2.1 Tablo Alan . . . . . . . . . . . 9.2.2 Sema . . . . . . . . . . . . . . . 9.2.3 Grnt . . . . . . . . . . . . . ou u 9.2.4 Dizi (Sequence) . . . . . . . . . 9.2.5 Tetik . . . . . . . . . . . . . . . 9.2.6 Dizi ve Tetik . . . . . . . . . . 9.2.7 Veri Taban Kprs . . . . . . o uu 9.2.8 Eanlam (Synonym) . . . . . . s 9.2.9 Indeksler . . . . . . . . . . . . . 9.2.10 Oracle SQL*Loader . . . . . . . 9.3 Transaction . . . . . . . . . . . . . . . . 9.4 Beklemeden Kitlemek . . . . . . . . . . 9.5 Kurmak . . . . . . . . . . . . . . . . . . 9.5.1 Linux Uzerinde Oracle . . . . . 9.5.2 Linux Uzerinde PostgreSQL . . 9.5.3 Linux Uzerinde Mysql . . . . . 10 Unix 10.1 Unix Aralar . . . . . . . . . . . . . . c 10.1.1 Komut Birletirme . . . . . . s 10.1.2 Sreler . . . . . . . . . . . . u c 10.1.3 Dosyalar . . . . . . . . . . . . 10.2 Kullanclar . . . . . . . . . . . . . . . 10.2.1 Dosya Haklar ve Kullanclar 10.3 Scripting . . . . . . . . . . . . . . . . . s 10.4 Makina Balaynca Program Iletmek . s sletmek . . . 10.5 Takvime Bal Program I g 10.6 Network Durumu . . . . . . . . . . . . 10.7 Yardm Almak . . . . . . . . . . . . . 10.8 X-Windows Kullanm . . . . . . . . . 11 Proje Ynetimi o 11.1 Karakterler . . . . . . . . . . . . 11.1.1 Proje Yneticisi . . . . . o 11.1.2 Teknik Lider . . . . . . 11.1.3 Programclar . . . . . . 11.2 Planlama . . . . . . . . . . . . . 11.2.1 Ne Kadar Ileri Grelim? o 11.2.2 UGB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

281 282 284 289 293 295 295 295 296 296 297 298 298 299 305 308 309 310 310 313 314 317 319 319 319 320 322 323 323 324 326 328 328 328 331 333 333 336 340 342 342 344

11.3

11.4

11.2.3 Kaynaklar, Zaman, Kalite, Fiyat Gelitirme Ortam . . . . . . . . . . . . . s 11.3.1 Test Ortamna Deployment . . . 11.3.2 Kaynak Kod Idaresi . . . . . . . 11.3.3 Kod Gzden Geirme Toplantlar o c 11.3.4 Kodlama Standartlar . . . . . . 11.3.5 Projelerde Hata Takip Dzeni . . u Kullanm Klavuzu . . . . . . . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

346 347 350 351 358 359 359 367 371 371 373 373 374 374 375 375 375 376 380 381 382 383 384 385 388 388 388 390 391 393 394 395 395 398 398 398 399 400 400

A Aralar c A.1 Ornek Kodlar . . . . . . . . . . . . . . . . . . A.1.1 Hibernate . . . . . . . . . . . . . . . A.1.2 Web . . . . . . . . . . . . . . . . . . A.1.3 Datk Nesneler . . . . . . . . . . . g A.2 Java . . . . . . . . . . . . . . . . . . . . . . . A.3 Ant . . . . . . . . . . . . . . . . . . . . . . . . A.3.1 Kurmak . . . . . . . . . . . . . . . . A.3.2 Kullanmak . . . . . . . . . . . . . . . A.3.3 Build.xml . . . . . . . . . . . . . . . A.4 JBoss . . . . . . . . . . . . . . . . . . . . . . A.4.1 Deploy Dizinleri . . . . . . . . . . . . A.4.2 Gelitirme Amal Port Deitirmek s c gs A.4.3 Kme Ortamnda Port Deitirmek . u gs A.5 Linux . . . . . . . . . . . . . . . . . . . . . . A.6 Cygwin . . . . . . . . . . . . . . . . . . . . . A.7 MySQL Front . . . . . . . . . . . . . . . . . . A.8 OpenSSH . . . . . . . . . . . . . . . . . . . . A.9 ITracker . . . . . . . . . . . . . . . . . . . . . A.10 Linux Uzerinde CVS . . . . . . . . . . . . . . A.10.1 Kullanmak . . . . . . . . . . . . . . . A.10.2 CVS ve Binary Dosyalar . . . . . . . A.11 Enscript . . . . . . . . . . . . . . . . . . . . . A.12 Emacs . . . . . . . . . . . . . . . . . . . . . . A.12.1 Emacs Ozellikleri . . . . . . . . . . . A.12.2 Emacs ve CTRL tuu . . . . . . . . s A.12.3 Ayar Deiiklikleri . . . . . . . . . . gs A.13 Cygwin Uzerinde X Windows . . . . . . . . . A.14 Kaynak Kod Yamalar . . . . . . . . . . . . . A.14.1 Yama Uretmek . . . . . . . . . . . . A.14.2 Yama Uygulamak . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

B D zenli Ifadeler u s B.1 Perl ile Metin Ileme . . . . . . . . B.1.1 Ckt Dosyas . . . . . . . B.1.2 Birok Giri Dosyas . . . c s B.2 Ifadeler . . . . . . . . . . . . . . . B.3 Gruplama ve Bulunan Kullanmak Kaynaka c

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

401 401 402 402 403 406 407

o Onsz

Bilgi ilem dnyas ahsma olduka zevkli bir kariyer salad. BASIC, C, ve s u s c g COBOL programlarn kitaplardan anlamaya ve kodlamaya uratm zamang s g lardan, imdi yksek lekli, Unix bazl Java ve SQL teknolojilerini kullanan s u oc kme mimarilerini kurabildiimiz zamanlar arasndaki projeler, ve bu projelu g erde kullanlan teknolojiler mthi bir deiim yaadlar. Neredeyse baladmz u s gs s s g yerden fersah fersah uzaktayz. Artk daha hzl, daha az hatal ve daha yksek u lekli programlar yazma ansmz var. Gelitirme aralarmz daha iyileti, ve oc s s c s iimizi byk lude rahatlatt. s u u o c Bu kadar teknoloji deiimine ramen, ilgin olan baz teknolojilerin hla gs g c a ayn kalmasdr. Mesel iletim sistemlerinden Unix hla bizimledir, ve taha s a minim odur ki daha uzun sre bizle olmaya devam edecektir. Ayn ekilde u s ilikisel veri tabanlar kendilerini ispatladklar 80li yllardan bu yana her s irkette bir demirba hline geldiler, ve olmaya devam edecekler. Bu gruba s s a en son katlan Java, kendine olduka salam bir yer edindi ve zm yelpazesi c g co u gittike geniliyor. Zannediyoruz ki kurumsal yazlmda optimal bir teknoloji c s demetine doru yaklayoruz. g s Elinizde tuttuunuz kitap, bu optimal demeti biraraya getirme yolunda g bir ilk denemedir. Bunun artk olabileceini yakn bir zaman nce farkederek, g o tm proje tecrbemizi birbirine uyacak bir ekilde sunmaya karar verdik. Son u u s nemli para olan kalclk (persistence) gelmesi en geciken parayd, fakat beko c c lediimize dedi sanyorum. Hibernate ak yazlm projesi ile artk yzmz g g c u u u kzarmadan bir kurumsal sistem mimarisini esnek bir kalclk zmyle sunco u u mamz mmkn olmutur. u u s Dnyada ve Trkiyede, hlen, yazlmam ve yazlmas gereken bir kurumu u a s sal yazlm potansiyeli (application backlog) mevcuttur, ve bu sebeple sektrmz ou u iin her seviyede ne kadar ok yeni teknik adam yetiirse o kadar iyi olacaktr. c c s Bu amala elinizde tuttuunuz kitap hem programclar, hem de teknik liderc g lere ynelik yazld. Yazlm projesinin beyni, merkezi olan ve ynn salayan o o u u g teknik liderlere verebileceim en iyi destei bu kitapla vermeye altm; Umarm g g c s baarl olabilmiizdir. s s xiii

Bu kitab yazarken tecrbelerinden yararlandm ve bana rnek olan inu g o sanlara teekkr etmek istiyorum. Onlar olmasa, elinizdeki sentez hibir zaman s u c gerektii gibi olmayacakt. g Oncelikle teknik lider ve arkadam Jim DAugustinee yazlm projelerinde s sosyal ve teknik iletiimi hakknda bana iyi bir rnek olduu iin teekkr eds o g c s u erim. Jim, altn kalbi, pr dikkati, bitmeyen enerjisi, ve veri tabanlar hakknda u engin bilgisi ile kurumsal bir projenin teknik ve teknik olmayan ihtiyalar c hakknda bana ok ey retmitir. Ayrca Jimin yazlm gereklilik listesini c s og s oluturma konusunda gsterdii detaya dikkat, benim iin zellikle retici s o g c o og olmutu. s Jim Menard, Emacs maestrosu, dil koleksiyoncusu, deli mucit, kafa insan, bazen konumasnn yetiemedii hzl zekas ile herkese iyi bir teknolojist s s g byle olmal dedirten kimlik olarak bana nce bol bol .emacs numaralar, daha o o sonra teknolojiye tamamen hakim olmamn ne demek olduunu gsterdi. Bir g o de Perl. Herkesin kodunda ayn ekilde yapt bir hatay Jim u satr Perl u s g c script ile deitirince, bu beceriyi renmem gerektiini anlamtm. gs og g s Programclk dnyasndaki ahsiyetlerden alttakilere teekkr bor bilirim: u s s uu c Kitaplarndan rendiim ve yazlmlarndan faydalandm kiiliklerden og g g s Richard Stallmana apka kartmak gerekiyor. Yazd Emacs adl editr 12 s c g ou sene sonra hla kullanmaktaym, ve baz zelliklerini hla yeni kefediyorum. a o a s Dilden dile atlayan bir teknik lider iin her dilde bir modu olan Emacs vazgeilmez c c bir aratr; Sn. Stallmana bu gzel ara, ve daha da nemlisi serbest yazlm c u c o hareketini balatm olduundan dolay iin teekkrler ediyorum. s s g c s u A Bu kitabn dizilmesinde (typesetting) kullandm L TEX programnn yazar g Donald Knuth nnde saygyla eilmekten baka are yok. Eer bu harika o u g s c g yazlm olmasayd, bu kitabn bu kadar hzl yazlmas ve dzgn formatta olu u A mas mmkn olmazd. Kitap ayrca L TEX uzerine kurulmu memoir paketini u u s kullanmaktadr, ve bu paketin yazar Peter Wilsona nce bu paketi yazd, ve o g e-mail uzerinden baz sorularm cevaplandrmakta gsterdii sabr iin teekkr o g c s u ediyorum. Nesnesel dnyada, Bertrand Meyera nesnesel bir dilin ve tasarmn nasl u olmas gerektiini ok nceden bulduu ve bizle paylat iin sayglar ve g c o g s g c teekkrler sunmak gerekiyor. Dr. Meyern tasarlad dil Eiel ticari olarak s u g hakettii kadar yaylmam olsa da, bu dili renmi olmak bizi dier dillerde g s og s g daha iyi bir programc yapmtr. Ayrca, Dr. Meyer ile Bostonda bir kons feransta tantmda comp.object, comp.lang.c++, comp.lang.eiffel grus g plarnda yazdklarm hatrlayp, imzalamas iin ona verdiim kitaba Usenetteki c g bizi dunmeye sevkedecek yorumlarn iin imdiden teekkrler kelimelerini us c s s u yazm olmas da benim iin apayr bir sevin kayna olmutu. Teekkrler Dr. s c c g s s u Meyer. Linus Torvaldsa, bize Intel mimarisi uzerinde hzl alan bir Unix olan c s Linuxu verdii, ve bylece artk kurumsal yazlmlarda nal mimari paras g o c olarak ucuz ve gvenilir bir Unix tavsiye edebilmemiz ve kullanabilmemize u imkan verdii iin sayglar ve teekkrler sunmak gerekiyor. Yksek lekli g c s u u oc

Linux bazl Java uygulamalar uzun zamandr mevcutlar, bu da Linuxun mevcudiyetinin sektrde eitlilik, seenek ve rekabet yaratm olduunun ciddi bir o c s c s g gstergesi. Ayrca Linus Torvalds, yazlm disiplini hakkndaki grleri ve o o us sektr analizleriyle biz kurumsal danmanlar iin tandk ve karde bir ruhtur; o s c s Hata ayklayc sevmemesine ve teknik proje idare yntemine gnlden katlyorum, o o u ve baka birok katlan olduunu biliyorum! s c g Kurumsal Java kitabnn tamam ak yazlm kullanlarak hazrlanmtr. c s Kitabn matbaadan direk baslmaya hazr PDFini uretmek iin L TEX, diya c A gramlar iin Dia1 , resimleri bir formattan dierine aktarmak iin ImageMagc g c ick2 , ve kitapta kullanlm olan rnek kurumsal kodlar test etmek iin Uygus o c lama Servisi olarak JBoss3 urn kullanld. Simdiye kadar ok faydalandm u u c g ak yazlm kltrne ben de JmxMonitor ve CmuCamJ projeleriyle bir eyler c u uu s geri vermeye uratm, umarm ileride daha fazlasn yapmam mmkn olur. g s u u Kurumsal Java kitabnn Trkiyedeki kurumsal yazlm sektrne yapc u ou bir etkisi olmasn umuyor, okurlara baarlar ve mutluluklar diliyorum. s Burak Bayraml Istanbul Kasm 2005

1 http://www.gnome.org/projects/dia 2 http://www.imagemagick.org 3 http://www.jboss.org

Bl m 1 ou

Giri s

Bu Bl mdekiler ou Kurumsal programclk tanm Niye bu kitap Blmlerin iindekiler ou c

1. GIRIS urumsal sistemler (enterprise systems), vazgeilmez bileeni olarak bir c s veri tabann ieren, kullancsna bir nyz salayan ve ayn anda birc o u g den fazla kullancy destekleyen sistemlere verilen addr. Kurumsal yazlmlar, irketlerin ya da organizasyonlarn veri alveriini idare ederler, ve bu idareyle s s s veriyi, stratejik bilgiye dontrmeye alarak yazlm kullanan irkete rakipus u c s s lerine kar bir fark/stnlk (dierentiator) salamaya alrlar. Bilgi ilem, s u u u g c s s ya da IT, bu sektrn dier adlardr. ou g Kurumsal yazlmlar gelitirmekle uzmanlam programclara, kurumsal s s s programc adn veriyoruz. Kurumsal programc, ya ii yazlm olmayan bir s irketin bilgi ilem blmnde, ya da ii irketlere yazlm danmanl vers s ou u s s s g mek olan danman (consulting) irketlerinde alr. Danmanlk irketinde s s c s s s kurumsal programc asal alandr, d dnyaya onun yapt i pazarlanr. c s s u g s Dier irketlerde destekleyici konumdadr; Programc, ii baka bir ey olan bir g s s s s irkete yazlm destei vermektedir. s g Bu kitabn tamamnn oda, kurumsal programcdr. Fakat kurumsal bir g yazlm uzerinde almyorsanz bile bu kitaptaki tavsiyelerin bir blm iinize c s ou u s yarayabilir; Mesel veri tabann sadece okuma amal ve onu da iindeki ou a c c c g veriyi hafzaya ykleyerek kullanan, ok kullancl ama d dnyaya hibir u c s u c nyz salamayan bir arka plan program kurumsal program saylamaz, ama o u g o tr bir yazlma faydal olacak tekniklerin bazlar bu kitapta bulunabilir, u mesel blm 5, 8, 4. Kullandnz programlama dili Java bile olmayabilir, bu a ou g durumda 5. blmdeki bir Web uygulamasn dardan test etmek iin JMeter ou s c kullanm ilginizi ekebilir. Web uygulamas bile yazmyor olabilirsiniz, fakat c masast, zengin nyz teknolojilerini kullanan bir uygulamann bile nesnesel u u o u tasarm tekniklerine ihtiyac olacaktr (8. blm). ou s I tecrbemiz balamnda ahsen uzun sre danmanlk sektrnde altmz u g s u s ou c s g iin, kitaptaki anektodlarn ve tecrbe nda paylalan tekniklerin ounlukla c u sg s c g danman irketlere dnk olmas normldir. Fakat tecrbemiz gsteriyor ki s s o u a u o danmanlar, sre kullanm, tasarm metotlar ve dier birok kurumsal pros u c g c gramclk metotlarnda hep ba ekmi ve yolgsterici olmulardr. Danmanlarn s c s o s s byle olmasnn sebebi tamamen iinde yaadklar sektrn onlarn uzerinde o c s ou mecbur brakt artlarla alkaldr; Mteri her zaman deiir, sk sk gelen g s a us gs projeler hep yeni bir yeni balang anlamna gelir. Danmann mterisi iin s c s us c yeni proje, kr potansiyelidir, ama bir yandan yeni teknoloji, risk anlamna a gelir ve bu risklerin azaltlmas iin baz yollar takip edilmelidir. Projeyi belli c bir zamanda yapmaya talep olarak riski uzerine alan danman irketi, yazlm s s kodlama (delivery) uzerinde en optimal yolu bulmak zorundadr, unk ge c u c kalan ya da daha kts bitmeyen bir proje, danmann irketi iin para ve ouu s s c un kayb anlamna gelir. Kurumsal Java kitabn takip edebilmek iin gereken bilgi seviyesi, temel c Java bilgisidir. Bu kitapta miras alma (inheritance), okyzllk (polymorc u uu phism) ya da dier Java szdizim teferruatlar ilenmeyecektir; Eer bu bilgilere g o s g ihtiyacnz var ise, temel Java hakknda gvenilir bir kaynaa bavurmanz u g s tavsiye ederiz. 2

BOLUM REHBERI

1.1

Bl m Rehberi ou

Kurumsal Java kitabn dz bir srada okumak gerekli deildir, zaten blmler u g ou sralama nem tayacak ekilde hazrlanmamtr. Eer Web bazl sistemleri o s s s g renmek istiyorsanz, 3. ve 2. blmlere direk olarak gidebilirsiniz. Bu blmlerde og ou ou Struts/JSTL bazl ve arka planda Hibernate teknolojisini kullanan bir Web sistemini kurmak iin gerekli tm teknikleri bulabilirsiniz. c u Eer uygulamamzdaki nyz, Swing gibi bir zengin nyz teknolojisi ise, g o u o u arka planda uzaktan nesne eriim, ya da genel adyla, datk nesne teknolojisi s g kullanmak zorundayz, ve bu yaygn teknolojilerin u tanesi, RMI, EJB Session c Bean ve JMS, 4. blmde detayl olarak anlatlmtr. Sahsen kariyerimizin ilk ou s projesinde bir datk nesne zm olan CORBA ile kurumsal kodlamaya g co u u balam olmamz, bu alanda bize olduka tecrbe (hem iyi hem kt) yaatt, s s c u ou s ve bu tecrbenin ekillendirdii tavsiyeleri de bu blmde bulacaksnz. u s g ou Bir kurumsal uygulamann hzl almas, en az doru almas kadar c s g c s nemlidir; Bu sebeple performans iyiletirmesi apayr bir blm olarak sunulmutur o s ou s (5. blm). Bu blmdeki bilgileri, ilgili olduu her teknolojinin blmlerine ou ou g ou koyarak datmak mmknd, fakat performans konusunun kendine has termig u u u nolojisi ve htta metadolojisi olmas sebebiyle, ayr bir blm olarak verilmesi a ou c kararlatrld. Olekleme ile ilgili konular ayn blmde bulabilirsiniz. s ou Uygulamamzn vazgeilmez tabakas, tm verilerin hem k ve hem de c u c s sonu noktas olan ilikisel veri tabanlarn 9. blmde anlatmaya altk. c s ou c s s Ilikisel tabanlarn temeli olan ilikisel model (relational model), ve eriim s s yntemi olan SQL burada ilendi. Her ne kadar Hibernate gibi kalclk teknoloo s jileri ile artk basmakalp SQL yazmaktan kurtulsak ta, yine de SQLi iyi bilmemiz gerekmektedir. Sonuta Hibernatein sorgulama dili olan HQL bile, c aslnda SQLin nesnesel bir versiyonudur. Ayrca uygulama iinden kullanma c ek olarak proje srasnda uygulama dndan test amal olarak veri tabannda s c ne olduunu anlamak iin SQL iletmek gerekmektedir. Bu yzden SQL ang c s u latm blme dahil edilmitir. ou s Nesnesel tasarm tekniklerini anlattmz 8. blmde nesnesel tasarmn g ou dier tasarm tekniklerinden farkn ve nesnesel tasarm yapmak iin gereken g c temel bilgileri vereceiz. Kurumsal yazlmlarda ok ie yarayacak baz kritik g c s nesnesel tasarm teknikleri de bu blmde gsterilecektir. Daha sonra, tm ou o u nesnesel modelleme numaralarnn biraraya geldii teknik mimarin ne olduunu g g da bu blmde trif edeceiz, ve bu trin teknik lider olmak isteyen herkes ou a g a tarafndan okumasn tavsiye ediyoruz. Gelitirme ve kabul testleri, kitabmzn nemli blmlerinden biri olacak s o ou (7. blm); Gelitirme srasnda kendi kendimizi kontrol mekanizmas olan ou s birim testlerini yazmay bu blmde iliyoruz. Ayrca gereklilikleri dardan ou s s (nyzden) test etmek iin gereken JMeter aracn kullanmay da ileyeceiz. o u c s g Test etme ilemi, projemizin ayrlmaz bir paras olarak kabul edilmelidir. s c Test yntemlerinden zellikle birim testleri gelitirme srecine ne kadar dahil o o s u edilebilirse, kendimizi o kadar iyi/baarl hissetmeliyiz. s 3

1. GIRIS Kitabmzn teknik taraf, iler hlde ve test edilmi rnek Java kodlar ile s a so destekleniyor; Bu rnek programlar dzgn, temiz yapda ve optimal alr o u u c s hle getirmek iin ok uratk, ve en az kitabn metni kadar nemli olduunu a c c g s o g dunyoruz. Ornek kodlarn nereden indirilecei ve kullanlaca A.1 blmnde us u g g ou u anlatld, kullanmak iin gereken programlar JBoss Uygulama Servisi, Java c derleyicisi, ve Ant derleme sisteminin nasl kurulacg yine blm A iinde a ou c bulunabilir. Projelerimizde ska kullandmz faydal programlarn tmnn c g u u u kuruluu blm A iinde anlatlmaktadr, buna tek istisna MySQL, Oracle ve s ou c PostgreSQLn nasl kurulacan anlatan 9.5 blmdr. g ou u u Bir uygulamann kodlamas bittikten sonra, ileyecei nihai yer olan sonu s g c (production) ortamna nasl gnderilecei, ve buraya gnderildikten sonra nasl o g o izlenip takip edilecei 6. blmde ileniyor. Bir kurumsal uygulama tipik olarak g ou s birok sreten meydana gelir; Uygulama servisi, veri taban ve web server c u c olarak dunrsek en az u tane Unix srecimiz olacaktr. Bu srelerin ayakta us u c u u c kalmas ve kerse tekrar ayaa kaldrlmalar kurumsal sistemlerde gerekli co g teknik numaralardandr; Bunlar yapabilmek iin gerekli scriptleri 6. blmde c ou bulacaksnz. Uygulamanzdan istatistik paylamak ve bu istatistiklerin uzers ine alarm artlar koyarak srekli, otomatik olarak takip edebilmek iin nce s u c o Java JMX teknolojisi ile bunlar nasl d dnya ile paylaacamz, ve sonra s u s g tarafmzdan yazlm bir ak yazlm projesi olan JmxMonitor ile bu istatiss c tikleri nasl takip edebileceimizi greceiz. g o g

1.2

T rke Kullanm u c

Kitabmzdaki Trke kullanmnda Sayilar ve Kuramlar blogunda takip ettiimiz u c g ayn dikkati vermeye zen gsterdik. Fakat rnek kodlarda ve karl yeterince o o o s g iyi olmayan kelimelerde o kelimelerin Ingilizcesini kullanmaya karar verdik. Ornek kodlar iin bunu planlamamtk. Fakat Trkiyedeki programclarn c s u Ingilizce kelimeler, ve deiken isimleri ile kodlama hususunda olduka hi bir gs c c problemi olmadn gzlemledik. Ayrca ilerideki bir tarihte elinizde tuttuunuz g o g kitabn Ingilizceye evirilmesi szkonusu olabilecei iin, rnek kodlarn Ingilizce c o g c o olmas kararlatrld. s Karl bulunamayan (ya da beenilmeyen) kelimelerde, mesel bir Ant s g g a taski, Ant targeti, ya da Unix scripti gibi, o kelimelerin olduu gibi kulg lanlmas kararlatrld. Ant kelimelerindeki sorun, bu terimlerin herhangi bir s karlnn sektrde kimse tarafndan ortaya atlmam olmasyd, yni ortada s g o s a bir konsenss yoktu. Eer bu kelimeler yerine grev, ve hedef karlklarn u g o s kullanacak olsaydk, o zaman Ant Ingilizce belgeleri ile ayrla decek, ve g us okuyucumuzun kafasn kartrm olacaktk. Ayrca bu kelimeler pek yaygn s s olan ve baka amalar iin kullanlan gerek hedef ve grev kelimeleriyle ayndrlar, s c c c o bu yzden hi deilse ayr bir ey olduu daha belli olan task ve target keu c g s g limelerinin kullanlmas bize daha mantkl gelmitir. Ayn durum, Trke karl s u c s g ilem olan transaction kelimesi iin de geerliydi. s c c 4

Ek Bilgiler Script Trkeye betik olarak evirilen, ve Trkesi ne yazk ki sektrde u c c u c o tutmayan bir kelimedir. Bu kelimenin kullanmn uzun sredir takip ediyor ve u ahsen de cmlelerimizin paras yapyorduk, fakat uyum bakmndan yeterli ols u c madna kanaat getirip, kelimenin orijinalini desteklemeye karar verdik. Betik g kelimesi, ses yaps ve uyumu asndan bir trl bir script szcunn gcne c u u o ug u u u eriememitir. Bizim Trke kelime seerken kstasmz, bir kelimenin anlatm s s u c c (cmle) iinde akc bir ekilde yer alabilmesi, ve o kelime uzerinden anlatlann, u c s anlalmasdr. Ayrca, bu kitap okunduktan sonra, burada edinilen bilgiler s hakknda yeni bilgiler edinilmek istendiinde, Ingilizce dokmanlarn programcya g u ok fazla yabanc gelmemesi dier bir amacmzd. Bu amala Trkesini kulc g c u c landmz bir terimin yanna muhakkak Ingilizcesini parantez iinde yazmaya g c dikkat ettik. Bylece, programc isterse, o kelimeyi Googleda arayabilecek, ya o da ilgili programn dokmantasyonunda tarama yaparak konuyla ilgili dier u g teferruatlar renme ansna kavuacaktr. og s s

1.3

Ek Bilgiler

Kitaba yorumlaryla yardmc olan ve hatalarn dzeltilmesine katkda bulunan u Java Teknoloji Derneindeki arkadalardan veri taban blmn okuyan Mug s ou u u rat Acara, Hibernate blmn okuyan Melih Sakaryaya ve Web blmn gzden ou u u ou u u o geiren Altu Altntaa (ve yorum yapan dier arkadalara) buradan teekkr c g s g s s u ediyorum. Geri kalan tm hatalarn sorumluluu bana aittir. u g Hatalar bulunduka, http://sayilarvekuramlar.blogspot.com/2008/ c 11/kurumsal-java-hatalar-1-basm.html adresinden (dzeltmeler ile birlikte) u paylalacaktr. Kitap ile ilgili dier bilgileri http://sayilarvekuramlar. s g blogspot.com adresinden bulabilirsiniz. Iyi okumalar, ve baarlar. s

1. GIRIS

Bl m 2 ou

Hibernate

Bu Bl mdekiler ou Hibernate projesini kuruluu, dizin yaps, Ant build.xml s ge ve kolon elemesi O s Nesneler aras ilikiler s Sorgulama

2. Hibernate

artsmasz, veri tabanna eriim, yni bir kayd eklemek, silmek, gncelle s a u mek gibi ilemler, kurumsal uygulamalarn en nemli blmn tekil s o ou u u s eder. Yaygn bilinen bir istatistie gre, bir kurumsal uygulamann veriye g o eriiminde harcanan zaman, uygulamann tamamnda harcanan zamana oranla s %80 kadar bir zaman tekil etmektedir. Bu oran, ok byk bir rakamdr ve s c u u kurumsal uygulamalarda veriye eriimin nemine iaret eder. s o s Java dnyasnda veriye eriim iin en temel yntem, JDBC (Java Database u s c o Connectivity) ad verilen bir ktphane uzerindendir. JDBC, Java ile veri tauu banlarna eriim iin piyasaya kan ilk zmdr. Cok temel olmas sebebiyle, s c c co u u JDBCnin programcya yapmasn izin verdii ilemler veri tabanna yakn ve g s SQL ile direk alkaldr: Sorgu iletmek, sorgulardan gelen sonular listeleyea s c bilmek, depolanm ilemleri (stored procedure) altrabilmek gibi. Veriye s s c s eriim teknolojileri klasmannda JDBC, DB ve uygulama arasnda ok ince s c u o u u bir tabakadr denebilir. Veri, uygulamaya tablolar kmesi olarak gzkr ve bu tablolar kmesi uzerindeki ilemler ile veri eklenir, gncellenir ve ya silinir. u s u

2.1

Faydalar

Kyasla nesnesel programclar, veriyi nesneler topluluu olarak grmeye alkndrlar. g o s Nesnesel tasarm takip eden bir programc iin veri, bir nesne iinde tutulac c bilen, ilenebilen, deitirilebilen ve Java temel tipleri uzerinden geri verilebilen s gs bir kavram olmaldr. Nesnesel dillerin izole etme (encapsulation) gibi zelliko leri, bu tr kodlama stilini ayrca zendirmekte, idare edilir hle getirmektedir. u o a Kod temizlii asndan da nesne odakl veri idaresinin daha makbul olduu g c g aktr. Uygulamamzn hem veri hem grsel tabakasnda veriyi alk olduumuz c o s g kodlama ve tayc birimler uzerinden grmek isteriz. Bu birimler, iinde get s o c ve set ieren basit Java nesneleri olacaktr. Bu basit Java nesne trne yeni c uu literatrde POJO ad da verilmektedir. POJO kelimesinin alm Plain Old u c Java Object (Basit Java Nesneleri) olarak bilinir. Ornek bir POJO aada s g gsteriliyor. o
public class Car { public Car() { } String licensePlate; public String getLicensePlate() { return licensePlate; } public void setLicensePlate(String newLicensePlate) { this.licensePlate = newLicensePlate; }

Faydalar
String description; public String getDescription() { return description; } public void setDescription(String newDescription) { this.description = newDescription; } }

Car nesnesi bir arabay temsil etmektedir, ve veri olarak iinde licensec Plate (plaka) ve description (trif) elerini tamaktadr. Araba nesnesi, a og s pr bir Java nesnesi olduu iin, her trl Java ilemine tbi olabilir; Bir listeye u g c u u s a eklenebilir, eleri dinamik olarak sorgulanabilir, hatta baka bir JVMe bile og s gnderilebilir. Yaplacak ilemler Java programn yazan programcnn hayali o s ile snrldr.

c Sekil 2.1: Iki Nesne ve Tablo Ieren bir Eleme s

Hibernate gibi teknolojilerin amac, kurumsal programclarn veriye eriim s ilemlerini tamamen POJOlar uzerinden yapmalarna imkan vermeleridir. Bir s POJOnun veri tabanna nasl elenmesi gerektiini eleme (mapping) dosyas s g s uzerinden anlayabilen Hibernate, bu noktadan sonra tm gerekli SQL ko u mutlarn dinamik olarak arka planda kendisi uretebilecektir. Yni bir tablo a uzerinde JDBC ile yaptmz SELECT, UPDATE, INSERT, DELETE ilemlerinin g s tm, tek bir eleme dosyas ile Hibernate tarafndan otomatik olarak yaplacaktr. u u s 9

2. Hibernate Aada araba nesnemizi veri taban tablosuna eleyen bir Hibernate dosyasn s g s gryoruz. ou
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <class name="Car" table="car"> <id name="licensePlate" column="license_plate"> <generator class="assigned"/> </id> <property name="description" column="description"/> </class> </hibernate-mapping>

Eleme dosyasndaki Car nesnesi, veri tabanndaki car tablosuna elenmektedir, s s ve tablonun her kolonunun hangi nesne esine elenmesi gerektii teker teker og s g belirtilmitir. Bundan sonra bir Car veri tabanna eklemek, u Hibernate kos s mutlarndan ibarettir.
Car car = new Car(); car.setLicensePlate(52 THU 34); car.setDescription(araba tanm 1) Session s = HibernateSession.openSession(); s.save(car);

Silmek iin s.delete(car), gncellemek (ya da eklemek) iin s.saveOrUpc u c date(car) kullanabiliriz. Grdumz gibi, her tablo iin drt SQL komutu yazmak yerine tek bir o ug u c o eleme dosyas uzerinden Hibernate veri eriiminin faydalar aktr. Kural #1 s s c balamnda Hibernate veri eriimi daha ksa bir dille gerekletirilmitir, ve g s c s s gene Kural #1 balamnda bir Hibernate eleme dosyas daha rahat baklabilir g s bir koddur. Eer, ileri bir zamanda car tablo isminin deimesi gerekse, SQL g gs artlarnda tm SELECT, UPDATE, INSERT, DELETE komutlarndaki tablo iss u minin deitirilmesi gerekecekti. Ya da, eer bir kolon ismi deise, o kolonu gs g gs kullanan tm SQLlerin deimesi gerekecekti; Fakat Hibernate kullanyorsak, u gs deien kolonun sadece nesne elemesini deitirerek, Hibernate uzerinden veriye gs s gs erien ilem kodlarda tek bir satr deitirmemiz gerekmez. s s gs Bu blmn geri kalannda, kurulu ve ana Hibernate kavramlarn ileyeceiz. ou u s s g Eer bu kavramlar atlayp, direk Hibernatein nasl kullanldn renmek isg g og tiyorsanz, tavsiyemiz 2.2.4 ve 2.2.5 blmlerine gz gezdirip, 2.4 blmne ou o ou u atlamanzdr. 10

Kurmak

2.2

Kurmak

Hibernate uzerinden erimek istediimiz her nesne (POJO) iin bir eleme s g c s dosyas yazlmaldr. Fakat proje baznda, sadece bir kez yaplmas gereken o ayarlar unlardr. Ilk nce, hibernate.cfg.xml gerekecek. hibernate.cfg. s xml dosyas, Hibernatee Veri tabanna nasl erieceini s g Hangi nbellek paketini kullanacan o g Onbellekleme ynteminin ne olacan o g Hangi veri taban balant havuzu (connection pool) kullanacan g g syler. Ayar dosyasnn CLASSPATHteki bir dizin iinde, ya da CLASSPATHteki o c bir jarn en ust seviyesinde olmas gereklidir. Buna uygun jar paketlemesi yapan rnek bir Ant build.xml scriptini, SimpleHibernate projesinde bulao bilirsiniz. Altta Car iin hazrlanm rnek bir hibernate.cfg.xml dosyasn gsteriyc so o oruz. Liste 2.1: hibernate.cfg.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory name="foo"> <property name="hibernate.connection.driver_class"> org.gjt.mm.mysql.Driver </property> <property name="hibernate.connection.url"> jdbc:mysql://localhost:3306/cars </property> <property name="hibernate.connection.username">user</property> <property name="hibernate.connection.password">pass</property> <property name="hibernate.connection.provider_class"> org.hibernate.connection.C3P0ConnectionProvider </property> <property name="hibernate.c3p0.min_size"> 5 </property> <property name="hibernate.c3p0.max_size"> 10

11

2. Hibernate
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

</property> <property name="hibernate.c3p0.idle_test_period"> 60 </property> <property name="dialect">org.hibernate.dialect.MySQLDialect </property> <property name="hibernate.cache.provider_class"> org.hibernate.cache.OSCacheProvider </property> <mapping resource="org/mycompany/kitapdemo/pojo/Car.hbm.xml"/> <class-cache class="org.mycompany.kitapdemo.pojo.Car" region="Simple" usage="read-write"/> </session-factory> </hibernate-configuration>

Satr satr aklama: c 10, 13: 10. satrda verilen deer, Hibernate tarafndan hangi JDBC g srcsnn kullanldn belirtiyor. Ornekte kullanlan deer, org. uu uu u g g gjt.mm.mysql.Driver adl MySQL srcsdr. Src parametresi, diuu uu u uu u rek JDBCye geilen parametrelerden biridir (evet Hibernate kendi ileyii c s s iin, arka planda JDBC kullanyor). MySQL srcsnn veri tabanna c uu uu u eriimi iin gerekli bilgiler 13. satrda verilmi; Mesel hangi makinaki s c s a hangi veri taban bilgisi. 15, 16: Tabana balanmak iin gerekli kullanc ismi ve ifre. g c s 18: Veri taban balant havuzu (connection pool) paketi. Ornekte seilen g c paket, C3P0 adl pakettir. Havuzlar hakknda detaylar 2.2.1 blmnde ou u bulabilirsiniz. 20 - 28: Balant havuzu iin gerekli parametreler (havuzun olabilecek g c en az, ve en ok byklu). c u u ug 29 - 32: Hangi veri taban iin, nasl SQL uretilmesi gerektii de buc g rada belirtiliyor. Src semek (MySQL, Oracle, vs), Hibernatein nasl uu u c SQL uretmesini belirlemek iin yeterli deildir. dialect parametresi ile, c g uretilen SQLin hangi taban iin olduu kesin olarak Hibernatee bildirme c g lidir. 34: Uygulamamzn kullanaca POJOlarn listesi mapping g resource ile Hibernatee bildiriyoruz. Orneimizde bir tane POJO tanmlyoruz: g 12

Kurmak Car. Hibernate, mapping resourceda belirtilen hbm.xml dosyasn CLASSPATHte bulacak, eleme tanmlarn ileyecek ve POJO uzerinden SQL s s uretmeye hazr hle getirecektir. a 35 - 38: Onbellek ayarlar. (Bu konunun detaylar 2.2.2 blmnde gsterou u o ilecektir).

2.2.1

Balant Havuzlar (Connection Pools) g

Bir bilgi ilem uygulamasnn yapabilecei en pahal ilemlerden biri veri tas g s banndan bir balant (connection) almaktr. Ozellikle uygulamanz Oracle g gibi ciddi bir taban uzerinde alyor ve bu tabann kontrol gvenlie ok c s u u g c nem veren bir adminin de elinde ise, balant alma srasnda birok ilemden o g c s (hafza hazrlama, vs. gibi) geilecei iin, balant alma ilemi kurumsal uyguc g c g s lamalarda en pahal ve yava ilemlerden biri hline gelmektedir. s s a Bu yzden, sistemin cevaplama zamann (response time) hzlandrmay u amalayan kurumsal programclar her ilem (transaction) banda srekli yeni c s s u bir balant ap, ilem sonunda bu balanty kapatan kodlar yazmaktan kanrlar. g c s g c Bunun yerine, balantlar uygulama banda bir kez alr ve bir tr balant g s c u g nbelleinde tutularak uygulamann ileyii boyunca ak tutulurlar. Balant o g s s c g nbellekleri, bir nevi havuzdur; Balantlar alp kapanmazlar, sadece bu oro g c tak havuzdan alnp geri verilirler. Bu havuzun belli sayda balant ieren g c bir havuz olmas zellikle nemlidir, unk her taban, ayn anda, sadece belli o o c u sayda balantya servis verebilir, ve optimal balant saysnn ustnde servis g g u vermenin veri tabannzn performans asndan kt sonular olacaktr. c ou c Piyasada Java/JDBC odakl birok havuz urn mevcuttur. DBCP, Proxc u u ool, C3P0 adl ak yazlm projeleri bu urnlerden sadece birkadr. Bahsedilen c u c projelerin her biri, Hibernate tarafndan kullanlabilen (hibernate.connection.provider_class parametresi ile) projelerdir.

2.2.2

Onbellek

Bir bilgi ilem uygulamas, eer bir veri birimini tabandan yazdndan daha s g g fazla okuyorsa, o veri birimi tabandan servislemek yerine hafzadan servisle mek daha hzl olacaktr. Onbellekleme (caching) tekniinin altnda yatan kir g zet olarak budur. Bir bilgi ilem uygulamasnn %80 kadar zamannn veri o s tabannda getiini dunrsek, diske ne kadar az gidersek veri eriimini (ve c g us u s bilahere uygulamann btnn) o kadar hzlandrm oluruz. uu u u s Onbellek kullanm, tek kullancl ve ok kullancl ortamlarda byk perc u u formans iyiletirmeleri getirebilir. Tek kullancl ortamda, ayn veriye birka s c kez erien (ayn) kullanc, birinci kullanmdan sonra ayn veriye tekrar eritiinde s s g o veriyi nbellekten ok hzl bir ekilde alabilmi olur. Cok kullancl ortamda o c s s (ayn JVMin birok ezamanl kullancya hizmet verdii artlarda) nbellek c s g s o 13

2. Hibernate kullanm daha da avantajldr; Kullanc Ann nbellee getirmesini tetikledii o g g bir nesneyi, kullanc B olduu gibi hafzadan kullanabilecektir. g Hibernate, kontrol altndaki tm nesneleri programcya hibir ek klfet geu u c u tirmeden programcnn istedii herhangi bir nbellek paketi uzerinde tutmasna g o izin vermektedir. Bu imdiye kadar yaln JDBC teknikleri ile elimizde olmayan s mthi bir esnekliktir. Dunn: Daha nce HashMap ya da elle yazlan bir u s us u o yap uzerinde olan nbellekleme, artk, Hibernatee verilen tek bir parametre o sayesinde otomatik olarak yaplyor olacaktr. Hibernate ncesi elimizle yapmamz gereken klfetli ilemler, pseudo kod o u s olarak altta gsterilmitir: o s
def araba_ykle(licensePlate : String) u begin Car tablosunda licensePlate kimlikli veriye eri. s Bu veri, hafzadaki HashMapte mevcut mu? begin Evet ise, hafzadakini dndr. o u Hayir ise, Tabandan ykle u HashMape yaz Geri dndr o u end end end def araba_sil(licensePlate : String) begin Veri HashMapte mevcut mu? begin Evet, hafizadakini sil, sonra tabandan sil Hayir, tabandan sil end end

Hibernate, kontrol altnda olan nesnelerin nasl ve ne zaman nbelleku o leceini nbellek paketlerine direk syleyebilir, unk tabandan okuma, silme, g o o c u yazma ve gncelleme ilemlerinin tm zaten Hibernate uzerinden yaplan u s u u ilemlerdir. Hibernate, bu noktalara engellenmi olan nbellek kodlar sayesinde s c s o bir nbellek paketini programcya hibir ek klfet getirmeden idare edebilir. o c u Yukarda pseudo kod olarak gsterilen eylemlerin tamam Hibernate iin gereko c siz hle gelmitir (Kural #2). a s Ayrca Hibernate, tek JVMde ileyen trden nbellekleri kullanabildii s u o g gibi, birden fazla JVM uzerinde alan ve birbirini a uzerinden gncelleyebilen c s g u datk nbellek urnlerini de kullanabilir. Datk nbellekler, a uzerinden g o u g o g birbirini senkronize edebilen urnlerdir. Onbellek kullanm ve datk nbellek u g o konularn 5.4.5 blmde daha detayl olarak greceiz. ou o g 14

Kurmak

2.2.3

Ornek Proje Dizin Yaps

Bir Hibernate projesinde gereken minimal dosyalar ve dizin yaps altta belirtilmitir. s
+- SimpleHibernate | +- build | +- lib | | +- activation.jar | | +- ant-antlr-1.6.2.jar | | +- antlr-2.7.4.jar | | +- c3p0-0.8.4.5.jar | | +- c3p0.license.txt | | +- cglib-full-2.0.2.jar | | +- commons-collections.jar | | .. .... | | +- jaxen-1.1-beta-4.jar | | +- junit-3.8.1.jar | | +- log4j-1.2.9.jar | | +- mysql-connector-java-3.0.16-ga-bin.jar | | +- oscache-2.1.jar | | +- xalan.jar | | +- xml-apis.jar | +- resources | | +- hibernate.cfg.xml | | +- log4j.properties | | +- oscache.properties | +- src | | +- java | | | +- org | | | | +- mycompany | | | | | +- kitapdemo | | | | | | +- dao | | | | | | | +- SimpleCarTest.java | | | | | | +- pojo | | | | | | | +- Car.hbm.xml | | | | | | | +- Car.java | | | | | | +- service | | | | | | | +- HibernateSession.java | | | | | | +- util | | | | | | | +- AllTest.java | | | | | | | +- ClassPathFile.java | | | | | | | +- TestUtil.java | | +- sql | | | +- sample_data.sql | | | +- tables_mysql.sql | +- build.properties | +- build.xml

15

2. Hibernate Bu dizinler ve ierikleri, SimpleHibernate projesinde bulunabilir. Simdi, bu c dizinde bulunan birimleri grelim. o

2.2.4

Hibernate Session

Hibernate ile veriye erimek iin, ncelikle bir org.hibernate.Session yaratp s c o bu nesne uzerinde openSession metotunu armak ve bir Hibernate oturumu c g balatmak gerekir. Ornek kodlarda grlen HibernateSession class, iinde s ou c bir Hibernate SessionFactory barndran yardmc bir nesnedir. Bu yardmc nesne rnek proje iin yazlm ve hazr olan bir koddur ve projenize olduu o c s g gibi eklenebilir. Bir org.hibernate.Session almak ve amak (openSession) iin Hiberc c nateSession nesnesindeki static arlar kullanabilirsiniz. HibernateSesc g sion classnn tm metotlar static metotlardr, bu yzden HibernateSesu u sionn bir nevi Singleton nesnesi olduu sylenebilir. Demek ki bir JVM g o iinde sadece bir aktif HibernateSession olabilir. HibernateSessiondaki c static blok, HibernateSession kullanlr kullanlmaz hemen arlaca iin c g g c hibernate.cfg.xml dosyalar okunmaya balar, ve referans edilen tm hbm s u .xml dosyalar takip edilerek gereken elemeler hafzaya alnr, ilenir, kontrol s s edilir ve nbellekte tutulur. o Static blok iinde yaplan dier nemli bir ilem, balant havuzu iin en az c g o s g c gereken balant (minimum connection count) says kadar balantnn hemen g g almasdr. Balant havuzlarn anlattmz 2.2.1 blmnde balant amann c g g ou u g c bir kurumsal uygulamada yaplabilecek en yava ilemlerden biri olduunu s s g aklamtk. Bu sebeple, HibernateSessiona erien ilk kod parasnn kulc s s c lancya dnk bir kod paras olmamas iyi olur. Niye? Cunk, bir kullancnn o u c u istedii basit bir sayfa/ekran iin, 100 tane taban balantsnn almasn bekg c g c lediini dunn! Bu ok yava bir sayfa yklemesi olacaktr! Tabii ki ayn sayfa g us u c s u ikinci kez istendiinde, cevap ok abuk dnecektir (gereken tm balantlar g c c o u g artk almtr), fakat o ilk yava sayfa yklemesi ile kullancnn aznda c s s u g kt bir tat brakmamak gerekir. Bu nedenle HibernateSessiona erien ilk ou s kod parasnn kullancya dnk kodlardan ayr, sadece uygulama balarken c o u s arlacak ayr bir kod parasndan olmasna zen gsterin. c g c o o Uygulamann geri kalan ksmnda, HibernateSession uzerinden aldnz g Session nesnesi ile istediiniz veri taban ilemini gerekletirebilirsiniz. Tek g s c s nesne ykleme, yazma, silme, ve sorgulama metotlarnn hepsi Session uzerinde u bulunmaktadr. s Iimiz bittikten sonra ise, HibernateSession.closeSession kullanarak Session kapatmamz gerekir, unk JDBC taban balantsn muhafaza eden c u g nesne Session nesnesidir; close ars ile veri taban balantsnn balant c g g g havuzuna dnmesini tetiklemi oluruz. Eer uygulama iinde hi close ars o s g c c c g yapmam olsaydk, uygulamamz bir sre sonra havuzdaki tm balantlar s u u g bitirecek ve uygulama ileyiine devam edemez hle gelecektir. s s a 16

Kurmak

2.2.5

Hibernate Transaction

Veri tabannda okuma, yazma, silme ilemleri yapan bir kod paras, iine s c s muhakkak beginTransaction() ile balamal ve commitTransaction() ile s iini bitmelidir. Ozetle Hibernate ile her yaptnz her ilemi alttaki kod blouyla s g s g sarmanz yararl olur.
try { Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); // ... // Hibernate ilemleri s // ... HibernateSession.commitTransaction(); } finally { HibernateSession.closeSession(); }

Kapan closeSession ileminin finally iinde konmas nemlidir, unk His s c o c u bernate operasyonunuz srasnda exception atlsa da, atlmasa da closeSession arsnn yaplmas bylece garanti olacaktr. c g o Transaction alkal arlarn HibernateSession vastas ile yapldna a c g g dikkat ediniz. Dier baz Hibernate rneklerinde bir Transaction nesnesinin g o sessiondan alnp, uzerinde direk olarak beginTransaction ve commit arlarnn c g yapldn grrz. Biz, iki sebeple bunu yapmayarak, tm Session ve Transg ouu u action alkal ilemleri HibernateSession uzerine aldk, unk a s c u 1. Session ve Transaction ile alakal tm ilemlerin tek bir yerde, tek bir u s class uzerinden olmas (kod idaresi ve temizlii asndan). g c 2. Session ve Transactionn sadece bir threade bal olmasn salamak g g Session ve Transaction niye bir threade balamak istedik? Cunk iinde g u c Hibernate ilemleri olan metotlarn birbirini zincirleme armas gerektiinde, s c g g her yeni arnn yeni bir transaction ve session balatmasn engellemek istiyc g s oruz. Bunun sebebi, kurumsal uygulamalarn %99unda bir metot dier metotu g arnca, her iki metotun da ayn transaction altnda olmasnn ok yaygn olc g c masdr. Ornek olarak, mesel bir bankada iki hesab arasnda para transferi a yapan bir kullancnn transferMoney adl bir ar yaptn dunn: c g g us u
AccountService service = ... service.transferMoney(100, 22993002,3399499

Gereken class tanmlar yle olsun: so 17

2. Hibernate
public class AccountService { public void transferMoney(double howMuch, String accountFrom, String accountTo) { Account fromAccount = ... Account toAccount = ... fromAccount.subtract(howMuch); toAccount.add(howMuch); } } public class Account { public void subtract(double howMuch) { .. } public void add(double howmuch) { .. } }

Bu kodda grldu gibi, bir hesaptan para eksiltmek ve yeni hesaba para o u ug eklemek ayn transaction altnda olmaldr. Aksi takdirde subtract (eksiltme) ileminden sonra servis makinasnn i ekilmi olsa, ekleme yaplmadan sistem s s c s km olaca iin para kaybolmu olurdu! Bu yzden transferMoney ile co us g c s u balayan metot zincirinin tamam ayn transaction altnda olmaldr. Bylece s o bu transaction altndaki tm ilemlerin ya hepsi baarsz olur, ya da hepsi ayn u s s anda baarl olur. s s Ite bu yzden metot zinciri ile transaction srekliliini birbirine balamalyz. u u g g Bunu yapmann en basit yolu ise, o anda ilemde olan thread ile (Thread.curs rentThread()) transaction birbirine balamaktr. Bunu HibernateSession g iinde ThreadLocal kodlama kalbn kullanarak [1, Sf. 301] yapabiliriz. Bu c kalp, o anki thread, Hibernate Session ve Transaction arasnda bir balant g kurmaktadr. Bylece zincirleme birbirine ar yapan metotlar ayn Thread o c g iinde olaca iin, ayn Transaction ve Session kullanlabilmi oluruz. c g c s

2.3

Kimlik Idaresi

s Ilikisel veri tabanlarnda bir satr tekil (unique) olarak belirleyebilmek iin, c anahtar grevini grecek bir ve ya daha fazla kolon tanmlamas gerekir. Bu o o kolon(lar)a, ilikisel (relational) veri taban dnyasnda asal anahtar (primary s u key) ad veriliyor. Tek bir satr bulmak iin SQL ile sorgu yaparken WHERE c ksmnda kullandmz ltreleme kolonlar, asal anahtar kolonlardr. g Hibernate, bir tablodaki tek bir satr tek bir nesneye elemek ister. Tablos daki her kolon da, bir POJO uzerindeki e (attribute) ile elenecektir. Bu og s eleme, eleme dosyasnda property kelimesi ile gerekletirilir. Fakat, asal s s c s anahtar oluturan kolon ve onun elendii nesne esi, ayr bir ekilde Hibers s g og s natee bildirilmelidir. Cunk Hibernate, bu eyi, dierlerinden ayr bir ekilde, u og g s nesneyi bulma, tanmlamak iin kullanlacak, yni nesnenin tekilliini belirten c a g 18

KIMLIK IDARESI bir e olacak kullanacaktr. Bu e, komut eleme dosyasnda <id> ile belirog og s tilir. Car rneimizi ele alrsak: o g
<hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <class name="Car" table="car"> <id name="licensePlate" column="license_plate"> <generator class="assigned"/> </id> <property name="description" column="description"/> </class> </hibernate-mapping>

Gsterilen Car nesnesinde tekil anahtar, licensePlate esidir, onun elendii o og s g kolon ise license_plate kolonudur. <id name="licensePlate"..> komutunu kullanarak, Hibernatee Car nesnesinin tekilliini licensePlate esi olduunu g og g bildirmi olduk. Bu e, Car nesnesini veri tabanndan yklerken get komutuna s og u anahtar olarak verilecek e olacaktr. og
Car car = (Car) s.get(Car.class, "34 TTD 2202");

2.3.1

Birden Fazla Kolon Anahtar Ise

Bazen bir tablodaki asal anahtar tek kolon deil, birden fazla kolon olabilir. Bu g durumda (SQL dnyasnda) bir satr tekil olarak bulabilmek iin asal anahtar u c oluturan tm anahtarlar WHERE komutuna veririz. s u Hibernate dnyasnda, bir nesneyi bulmak iin birden fazla e kimlik u c og olarak gerektiinde, eleme dosyasnn anahtar belirtilen blmnde <id> yerg s ou u ine <composite-id> komutunu kullanmak gerekecektir. Person rnek classnda o bu teknii grelim: g o Liste 2.2: Person.hbm.xml
<class name="Person" table="person"> <composite-id name="id" class="Person\$Id"> <key-property name="firstName"/> <key-property name="lastName"/> </composite-id> .... </class>

Liste 2.3: Person.java


package org.mycompany.kitapdemo.pojo; public class Person { public Person() { }

19

2. Hibernate
Id id; public Id getId() { return id; } public void setId(Id newId) { this.id = newId; } /** * Inline Id class * */ public static class Id implements Serializable { public Id(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public Id() {} String firstName; public String getFirstName() { return firstName; } public void setFirstName(String newFirstName) { this.firstName = newFirstName; } String lastName; public String getLastName() { return lastName; } public void setLastName(String newLastName) { this.lastName = newLastName; } } // dier eler ve onlarn get/set g og // arlar buraya c g // ...

20

KIMLIK IDARESI

Orneimizde Person asal anahtar, firstName (isim) ve lastName (soyisim) ikg ilisinden olumaktadr. Hibernatee bu ikiliyi bir asal anahtar olarak vermemiz s iin, firstName ve lastNamei ieren Id isminde yeni bir i class (inner class) c c c yaratmamz gerekti. Bu class, daha sonra composite-id komutuna parametre olarak geilmitir. c s Not: Kod idaresi asndan, Id classn Person iine koyarak bir c c i class hline getirdik, ama Id, apayr bir class olarak kendi .java c a dosyasnda da olabilirdi. Kodun dzenli olmas bakmndan Person u ile alkal her eyin tek yerde olmasn istediimiz iin, bu kodlama a s g c ekilde daha faydal bulduk. s Eer bir Person nesnesini get ile yklemek istiyorsak, bir i class Id nesnesi g u c yaratmal ve nesneyi parametre olarak get komutuna gemeliyiz. c
Session session = HibernateSession.openSession(); Person.Id id = new Person.Id(ahmet, ylmaz); Person p = (Person) session.get(Person.class, id); ...

2.3.2

Anahtar Uretimi

Anahtarlar konusunda dier nemli bir husus, anahtar atama sorumluluun g o g kimde olduudur. Baz uygulamalarda asal anahtar, verinin kendi iinden doal g c g olarak kar. Mesel veri operatrleri person tablosuna veri eklerken, kii isim c a o s ve soyadna gireceklerdir, ve bunu yaparken bir asal anahtar da otomatik olarak eklemi olacaklardr. Cunk person iin asal anahtar, firstName ve lastName s u c kolonlarnn bir kombinasyonudur. Fakat baz durumlarda asal anahtar verinin iinden kmayabilir. Bu artlarda c c s her satr tekil olarak kimlikleyebilmek iin bir asal anahtar uretmek gerekecekc tir. Anahtar uretimi (ya da uretilmemesi gerektiini) Hibernatee <id> etiketi g altnda <generator class=".."/> komutu ile tanmlyoruz. Eer bir anahtar g verinin iinden doal olarak kyorsa, hibir anahtar uretim eyleminin yaplmamas c g c c gerektii Hibernatee <generator class="assigned"/> ile bildirilir. Eer IDnin g g uretilmesi gerekiyorsa, en basit yntem olarak <generator class="incre o ment"/> kullanlr. Bu yntem, Integer bazndaki bir ID esinin (ve koloo og nunun) her yeni deerini bir ncekinden bir fazla olarak hesaplar ve tabana g o otomatik olarak yazar. Increment ile tanmlanan nesne esinin java.lang og .Integer olmas gerektiini bir daha vurgulayalm. g Eer id uretimini veri tabanna brakmak istiyorsanz, Hibernate de <geng erator class="native"/> kullanabilirsiniz. Bu seim ile, mesel MySQL uzerinde c a 21

2. Hibernate auto-increment id uretim yntemi, Oracle uzerinde ise sequence ile id uretimi o yntemi kullanlacaktr1 . o ID uretmek iin dier yntemler de mevcuttur. Bu ek metotlar Hiber c g o nate sitesi www.hibernate.org adresinden, ya da Hibernate yaratclarnn kitabndan [1] bulabilirsiniz.

2.4

Drt Ilem o s

Hibernatei kurup, HibernateSession uzerinden veri tabanna erimeyi hallet s tikten sonra, artk drt ilem ile tek bir nesneyi eklemeye, okumaya, deitirip o s gs yazmaya ve gerekirse silmeye hazrz. Bu ilemlere veri taban dnyasnda s u CRUD (CReate Update Delete) ilemleri ismi verilmektedir. Her ne kadar s nceki blmlerde Hibernate ile drt ilem ksmen anlatlm olsa da, toplu bir o ou o s s zeti bu blmde vermeye alacaz. o ou c s g Elimizde bir kimlik deeri var ve bu kimlik ile bir nesneyi bulup hafzaya g getirmek istiyorsak, bunu yapmak iin Session uzerinden get komutunu kulc lanrz.
Car car = (Car) s.get(Car.class, "34 TTD 2202");

Bir nesneyi bulup ykledikten sonra, onun uzerinde veri deiikliklerini, nesu gs nenin set metotlarn ararak gerekletirebiliriz. c g c s
... car.setDescription(yeni araba);

Fakat bu deiiklikler hla veri tabanna yansm deildir. Bu son aamay da gs a s g s tamamlamak iin, s.saveOrUpdate metotunu armamz gerekiyor. c c g
... s.saveOrUpdate(car);

Deiik bir senaryo, bir nesneyi yklemeden, yeni bir nesneyi sfrdan yaratp gs u bu nesneyi veri tabanna ekleme senaryosudur. Bu senaryo iin, new Car() c kullanarak yeni nesneyi yaratp, uzerinde ayn saveOrUpdate arsn yap c g mamz gerekir. saveOrUpdate metotu akll bir metottur; Kendisine verilen car nesnesinin iine (verisine) bakarak, bu nesnenin yeni mi, yoksa eskinin c gncellenmi hli mi olup olmadn anlama yeteneine sahiptir. Bylece ayn u s a g g o saveOrUpdate ars ile hem gncelleme hem ekleme ilemini yapabiliyoruz, c g u s ve bu ary yapan uygulama kodlarmzn nesnenin yeni mi eski mi olduunu c g g bilmesi gerekmiyor. Bir nesneyi (ve o nesnenin elenmi olduu veri satrn) veri tabanndan s s g silmek iin, Session uzerinde delete ars yaplr. Bu ardan nce, get c c g c g o
1 Hibernate native teknii kullanlnca aklda tutulmas gereken nemli bir nokta, Hig o bernate 2.0 versiyonunda native kullanmyla beraber unsaved-value=0 tanmnn id etiketi iinde kullanlmasdr. Hibernate 3.0 ile bu tanmn yaplmas gerekli deildir; Zac g ten Kitabmz Hibernate 3.0 versiyonu baz alnarak yazlmtr s

22

NESNELER ARASI ILISKILER ile nesnenin yklenmi olmas gerekmektedir (tabii perde arkasnda Hibernate u s gereken SELECT ilemini sonraya brakarak ekstra SELECTten bizi kurtarr). Bu s kullanm yledir: so
Car car = (Car) s.get(Car.class, "34 TTD 2202"); s.delete(car);

Tabii bu ilemlerden nce ve sonra HibernateSession yardmc nesnesi uzerinden s o session alp, bir transaction balatp bitirmeyi hatrlamamz gerekiyor (bkz. s 2.2.5). Ancak bir transaction commit edildikten sonra yaptmz deiiklikler g gs veri tabanna yansyacaktr.

2.5

s Nesneler Aras Ilikiler

s Hibernate gibi bir Nesne-Ilikisel Eleme (Object Relational Mapping - ORM) s aracnn belki de en nemli faydalarndan biri, iki tablo arasndaki yabanc o anahtarlar (foreign keys) uzerinden kurulmu bir ilikiyi, direk nesnesel bir s s iliki ekline dntrebilmesidir. Bunu yapabilmek iin, doal olarak, eleme s s o us u c g s dosyasnda gerekli ayarlar programc verecektir. Fakat bu komutlar verildikten sonra Hibernate, arka planda bir tablodan tekine, yni bir nesneden o a ilikili olduu dier nesneye atlamamz salayacak SQL komutlarn otomatik s g g g olarak uretecektir! Programcya, Java seviyesinde sadece nesne.getOtherOb jectList() gibi bir ar yapmak kalacaktr. c g Iki nesne (ya da tablo) arasnda, nicelik (cardinality) asndan deiik 3 tr c gs u iliki olabilir. Tek nesne Ann tek nesne B ile birebir, tek nesne Ann birok s c B nesnesi ile bireok, ve birok A nesnesinin birok B nesnesi arasnda okaok c c c c c ilikileri. Bu iliki eitlerini ve Hibernate eleme dosyasnda nasl temsil ediles s c s s ceklerini teker teker grelim. o

2.5.1

s Bire Bir (One to One) Iliki

Veri tabannda tek bir satrn dier tek bir satra iaret etmesi, bire bir trnden g s uu bir ilikidir. Hibernate bu ekilde bir ilikiyi, <many-to-one> etiketi ile desteks s s ler. Bire bir ilikisi, veri taban seviyesinde bir ya da daha fazla kolon uzerinden s gerekletirilebilir. Eer iaret edilen tabloyu tekil olarak belirlemek iin birc s g s c den fazla kolon gerekiyorsa, iaret eden taraf asal anahtar oluturan bu kolons s larn hepsini kendi uzerinde tamak zorundadr. Mesel, asal anahtar name ve s a person_lastnameden oluan person tablosuna iaret eden herhangi bir POJO s s eleme tanm, unlar iermek zorundadr. s s c
<many-to-one name="person" class="Person" not-null="true"> <column name="name"/> <column name="person_lastname"/> </many-to-one>

23

2. Hibernate POJO class iinde, person ilikisine tekabl eden get ve set metotlarn c s u eklemeliyiz.
.. Person person; public Person getPerson() { return person; } public void setPerson(Person newPerson) { this.person = newPerson; } ..

Bu iliki rneini HibernateComposite projesinde bulabilirsiniz. s o g


CAR
+LICENSE_PLATE +NAME +PERSON_LASTNAME

PERSON
+FIRST_NAME +LAST_NAME

s Sekil 2.2: Person Car Bire Bir Ilikisi

2.5.2

s Bire Cok (One to Many) Iliki

Kurumsal uygumalarda en ok lzm olan iliki tr, bire ok trden ilikidir. c a s uu c u s Ornek olarak gerek hayattan iki nesneyi alalm: Garage (garaj) ve Car (araba). c Diyelim ki bir garajda birok araba durabilir. Garage ve Car arasndaki bu c trden bir nicelik ilikisine, bire ok trden iliki diyoruz. Bu ilikide, tek u s c u s s Garage nesnesi (garage tablosundaki tek bir satr) birok car nesnesi ile (carda c birok satr) arasnda bir iliki olacaktr. Veri tabannda bu ilikiyi kurmann c s s yolu, bire ok ilikinin ok tarafna, bir tarafndaki asal anahtar alp, yabanc c s c anahtar olarak yerletirmektir. Bu yaplnca, mesel garage.id = 1 ltresi ile, s a 1 nolu Garage ile ilikide olan tm car kolonlarn bulmak mmkndr. s u u u u
select * from car where garage_id = 1

ile ilikideki tm arabalar bulunabilir. s u


GARAGE
+ID

CAR
+LICENSE_PLATE +GARAGE_ID

s Sekil 2.3: Garage ve Car Bire Cok Ilikisi

24

NESNELER ARASI ILISKILER Ayarlar Hibernatee bire ok trnden ilikiyi yanstmak iin eleme dosyasnda bir c uu s c s c tarafnda <set> komutu kullanyoruz. Iinde araba nesnelerini tutacak olan bir java.util.Set listesini de, Garage kodu uzerine yeni bir e olarak ekleyeceiz. og g Ornek Garage.hbm.xml ve Car.hbm.xml dosyalarn altta gsteriyoruz. o Liste 2.4: Garage.hbm.xml
<hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <class name="Garage" table="garage"> <id name="garageId" column="id"> <generator class="increment"/> </id> ... <set name="cars" inverse="true" cascade="save-update, all-delete-orphan"> <key> <column name="garage_id"/> </key> <one-to-many class="Car"/> </set> </class> </hibernate-mapping>

Liste 2.5: Car.hbm.xml


<hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <class name="Car" table="car"> <id name="licensePlate" column="license_plate"> <generator class="assigned"/> </id> ... <many-to-one name="garage" column="garage_id" class="Garage" not-null="true"/> </class> </hibernate-mapping>

Java kodlar da yle olacaktr. so


public class Garage { ... Set cars;

25

2. Hibernate
public Set getCars() { return cars; } public void setCars(Set newCars) { this.cars = newCars; } .. } public class Car { .. Garage garage; public Garage getGarage() { return garage; } public void setGarage(Garage newGarage) { this.garage = newGarage; } .. }

Not: Hibernate eleme ve Java seviyesindeki tip uyumlar ok kat s c olarak kontrol edilir; Mesel elemede <set> kullanp POJO uzerinde a s java.util.List kullansaydnz (ki bu yanl olurdu), Hibernate s uygulamanz baladnda bu hatay bulacaktr. s g Artk bu eleme uzerinden bir nesneden dierine pr Java arlar kullas g u c g narak geebiliriz. c
Set cars = garage.getCars();

Cascade <set> tanm paras olan cascade="all-delete-orphan", bire ok ilikiyi c c s daha da gclendirecek bir tanmdr. Cascade kelimesi Ingilizcede olaylarn u nce birinin, sonra tekisi olacak ekilde, srayla olmas anlamna gelir. allo o s delete-orphan ileminin cascade eklinde olmasnn istenmesi demek, ilikinin s s s bir tarafndaki nesne silindii zaman (delete), bu silme ileminin <set> iindeki g s c tm nesnelere etki etmesi, yani ilikide olan dier nesnelerin de silinmesi anu s g lamna gelir. Bu ok gl bir ilikidir, ve gerek dnya uygulamalarnn veri c uc u s c u modellerindeki her bire ok iliki iin uygun deildir. Sadece rnek amal c s c g o c olarak Garage ile Car arasnda byle bir iliki kurduk, yoksa, norml ziko s a sel dnya artlarnda bir garaj silinince iindeki arabalarn silinmesi yanl u s c s olurdu. 26

NESNELER ARASI ILISKILER Cascade iin kullanlm dier seenek save-update, Garageda alnan listc s g c eye garage.getCars().add(car) ile yeni bir nesne eklenir eklenmez, bu eklemenin veri tabanna yanstlmasn salar; Bylece yeni Car nesnesi uzerinde g o ayrca bir session.save ars yaplmasna gerek kalmaz. c g Eklemek Iki nesne arasnda bire ok iliki kurulduu zaman, eer ok tarafndaki nesnelc s g g c erden tabana bir tane daha eklemek istersek, bunu bir tarafndaki nesneden ok c taraf nesnesinin listesini alp, o liste uzerinde ekleme yapmakla halletmemiz gerekiyor. Ayrca, yeni eklenen nesne uzerinde, geriye, bir tarafndaki nesneye iaret eden referansa doru referans set etmeliyiz. Bir Car eklemek iin alttaki s g c rnek kodlar kullanlacaktr. o
HibernateSession.beginTransaction(); Garage garage = (Garage) s.get(Garage.class, new Integer(1)); Car car = new Car(); car.setLicensePlate("falanfilan"); car.setDescription("falanfilan"); garage.getCars().add(car); car.setGarage(garage); HibernateSession.commitTransaction();

Fakat uzerine ekleme yaptmz java.util.Set, temel Java tiplerinden biridir, g o zaman uzerine ekleme yaptmz anda Hibernatein bu ekleme ileminden g s nasl haberi olmaktadr? CGLIB sayesinde: Bir eleme dosyas ile POJOlarmz s Hibernatee tanttmzda, bu POJOlar ustnde kullanlan java.util.Set g u kodlar CGLIB tarafndan deiime uratlmaktadr, ve bylece deimi bu gs g o gs s nesnelerde olan her deiimden Hibernate de haberdar olmaktadr. O zaman bu gs deitirilmi listeye yeni bir POJO eklenince, Hibernate, bu ilemi yeni bir veri gs s s satr eklenmesi ve iliki kolonlarnn gncellenmesi istei gibi alglayabilecektir. s u g

2.5.3

s Coka Cok (Many to Many) Iliki

Bire ok rneinde, garaj ve araba arasnda okluu sadece bir tarafa gelecek c o g c g ekilde koymutuk. Bu veri tasarmna gre, bir araba sadece bir garaj altnda s s o olabiliyordu. Eer bu kstlamay kaldrp, ayn arabann fazla garaj altnda g olabilmesine izin vermek istiyorsak (her ne kadar ziksel dnyaya pek uymasa u da), o zaman oka ok trnden bir ilikiye gitmemiz gerekiyor. c c uu s Veri tasarm asndan oka ok ilikilere ucunc bir balant tablosu (link c c c s u g s table) gerekir. Ilikide olmas istenilen iki tablodaki iki satrn kimlik nolar balant tablosuna yeni bir satr olarak beraber yazlnca, iki satr ilikilendirilmi g s s olur. Balant tablosu, sadece iki kimlik kolonu ieren ok basit bir tablodur. g c c 27

2. Hibernate Hibernatee oka ok iliki ieren bir emay kabul ettirmek olduka koc c s c s c laydr, unk <set> ilikinin kendisine de bir tablo ismi verilebilir. Bu tablo c u s ismi, Hibernate tarafndan herhangi bir nesneye deil, <set> ilikisinin keng s disine ait bir tablo olarak alglanacaktr. Istediimiz balant tablosu ismini g g burada verebiliriz.
<hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <class name="Garage" table="garage"> ... <set name="cars" table="garage_car" lazy="true" cascade="save-update"> <key> <column name="garage_id"/> </key> <many-to-many class="Car" column="license_plate"/> </set> </class> </hibernate-mapping>

Tablo garage_car tablosu, iliki tablosu olarak grev yapan tablodur. s o Kullanm olarak, iki nesne arasnda ekstra bir iliki tablosunun olmamas s hibir eyi deitirmeyecektir (ve bu kod temizlii asndan ok iyidir). Coka c s gs g c c ok iliki uzerinden ok tarafndaki listeyi almak, ya da ok tarafna yeni bir c s c c nesne eklemek, bireok tekniindeki ile ayndr. c g Coka ok iliki rnek kodlar HibernateManyToMany kodlar iinde bulun c s o c abilir.

2.5.4

Sralanm Set Almak s

Eer Set ile alnan araba listesini sral bir ekilde almak istersek, <set g s > komutunun iinde order-by ek komutunu kullanabiliriz. Mesel Garagedan c a aldmz Car listesinin araba plaka kolonuna gre sralanmasn istiyorsak, altg o taki tanm kullanabiliriz.
<hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <class name="Garage" table="garage"> ... <set name="cars"

GARAGE
+ID

GARAGE_CAR
+LICENSE_PLATE +GARAGE_ID

CAR
+LICENSE_PLATE

s Sekil 2.4: Garage, Car ve Coka Cok Ilikisi 28

Sorgular
... order-by="license_plate asc"> ... </set> </class> </hibernate-mapping>

Liste sralanrken, yukardan aaya doru indike license_platein artmasn s g g c (adan zye doru) istiyorsak asc, azalmasn istiyorsak desc komutunu kullang malyz.

2.6

Sorgular

Kurumsal uygulamamzn veriye eriim ihtiyalar bazen tek bir nesneden balayarak s c s o nesnenin ilikilerinin gezildii trden, bazen de (istenilen sonucu almak iin s g u c tm parametrelerin elde olduu durumda) tek sorgu ile iin bitirilebilecei u g s g trden olabilir. u Nesne gezmek ynteminde, get ile yklenen tek nesneden dier nesnelere ato u g lanarak istenen veriye eriilmesi salanr. Bu tr veriye eriimi grsel arayz olan s g u s o u u uygulamalarda olduka sk olarak kullanlr, unk kullanc, her sayfada sadece c c u belli lude veriye bakabilir, ve yeni sayfalar istendike sonraki sayfalarda o o c c nceki verilerle ilintili dier verilere geilmesi gerekir. Bu yntemde, Hibernate o g c o uzerinden nesne dnyasna get yaplan bir giriten sonra bire bir, bire ok, u s c

Bire bir

A
+A_ID +B_ID

B
+B_ID

Bire ok

A
+A_ID

B
+B_ID +A_ID

oka ok

A
+A_ID

X
+A_ID +B_ID

B
+B_ID

s Sekil 2.5: Iliki Trleri ve Veri Taban u 29

2. Hibernate oka ok ve ilikiler gezilerek gereken verilerin alnmas (kullancnn ihtiyacna c c s gre) halledilebilir. o Parametre bazl bilgi toplama tekniinde ise, istenilen veriye ulamak iin g s c gereken tm parametreler elde vardr, ve bu parametreler uzerinden uygulanan u bir sorgu ile sonucun direk alnabilmesi beklenir. SQL dnyasnda, parametreli direk eriimi yapmann yolu, lazm olan tm u s u tablolar JOIN komutu ile birletirmek, ve gereken satrlar WHERE iindeki ls c treleme tanmlar ile ekip kartmaktr. Bu tr kullanmlarda tek bir Hibernate c c u get komutu ile etrel ltreleme gerektiren parametreleri kullanamayacamza c g gre, Hibernatein sorgulama tekniklerini tanmamz gerekiyor. o Hibernate, SQLe ok benzeyen bir eit sorgulama dilini destekler. Ayrca c c s Hibernate, srm 3.0dan itibaren direk SQL iletip sonular POJO listesi uu s c olarak dndrebilme zelliine de sahiptir, fakat birazdan greceiniz gibi HQL o u o g o g dili Hibernatein zaten elinde olan eleme bilgilerini kullanarak SQLdan ok s c daha esnek sorgular yapmamz salamaktadr (SQL ile sorgulayp cevaplar g POJOlar olarak almay daha sonra 2.6.5 blmnde greceiz). ou u o g

2.6.1

Basit Bir Sorgu

Tabandaki tm garage satrlarn almamz salayacak bir HQL sorgusu yazalm. u g Kod idaresi asndan, her sorguyu bir DAO nesnesine koymamz uygun olur. c Her POJO iin bir DAO yazabiliriz. Garage POJOsu iin byle bir class altta c c o gsteriliyor. o Liste 2.6: GarageDAO.java
package org.mycompany.kitapdemo.dao; import import import import import import import java.sql.*; org.mycompany.kitapdemo.util.*; org.mycompany.kitapdemo.pojo.*; org.mycompany.kitapdemo.service.*; org.hibernate.*; org.hibernate.cfg.*; java.util.*;

public class GarageDAO { public GarageDAO() { HibernateSession.beginTransaction(); } public List getAll() { Query query = null; Session s = HibernateSession.openSession(); query = s.createQuery("select garage from Garage garage"); return query.list();

30

Sorgular
} }

Ornek sorgu olarak kullanlan from Garage HQL sorgusundan gelen sonu, c bir List nesnesi olarak getAlldan geri dnlmtr. Eer sorgunuzdan tek o u us u g bir satr sonu geleceinden eminseniz, Query nesnesinden list() almak yerine c g uniqueResult() arsn yapabilirsiniz. Bu ar, bir liste yerine, tek bir nesne c g c g almanz salayacaktr; Bylece sonuca erimek iin list.get(0) gibi ek bir g o s c ar yapmanza gerek kalmaz. c g

2.6.2

c Join Ieren Sorgular

Diyelim ki, sorgudan istediimiz daha kark bir istek yle olsun; Kolon deg s so scription uzerinde rnek description 1 metnini ieren arabalarn garajlarnn o c bir listesini isteyelim. Bu sorgu iin SQL dnyasnda bir JOIN ile garage ve c u car tablosu birletirilir, kartezyen birleimi uzerinden garage_idsi uyanlar ve s s car tablosu uzerindeki description kolonunda rnek description 1 metnini o tayanlar ltrelenirdi. s Ama HQL dilinde kartezyen birleimini yapmak iin teker teker kolon bes c lirtmeye gerek yoktur. Zaten elimizde Garage nesnesinden Car nesnesine gitmemizi salayacak bir Hibernate iliki tanm vardr. Bu iliki tanm Hibernate g s s tarafndan garage ve car birletirmek iin zaten kullanlmaktayd, ve HQL, s c ayn iliki ismini hem tek nesneden gezmek hem de bir sorguda birletirim iin s s c kullanabilir. O zaman cars ilikisi uzerinden bir sorgu yle olur: s so
public List getGaragesForCars(String description) { Session s = HibernateSession.openSession(); Query query = s.createQuery( "select garage from Garage garage " + "left join garage.cars car " + "where car.description = :description " ); query.setString("description", description); return query.list(); }

Sorguda join garage.cars adl Hibernate <set> ilikisinin ismini kullanarak, s Hibernatein eleme dosyalarndan daha nce de tand iki tabloyu birletirmi s o g s s olduk. Kural #1e uygun olarak SQL ile kullanacazdan daha ksa bir dil kulg lanyoruz: Bu teknik iki tablo arasndaki balant kuran anahtarlar birden fazla g olunca daha da yararldr. Byle bir durumda SQL dili tm iliki kolonlarnn o u s kullanlmasn gerektirecekti ve dil kullanm iyice uzayacakt. Kyasla HQL iin yeni kolonlarn hibir etkisi olmayacaktr, hl ayn tek kelime ile (iliki c c aa s ismi) tablolar birletirebiliyor oluruz. s 31

2. Hibernate Parametre bazl ltrelemeyi gerekletirmek iin, garage.cars ilikisinin c s c s yeni ismi olan car uzerinden descriptiona eriiriz ve ltreleme artmz be s s lirtiriz. En son olarak sonular query.list() ile Hibernateden alrz. c

2.6.3

Sorgular ve Isimli Parametreler

HQL dilinin JDBC ile SQL yapmaya bir ustn taraf daha vardr, o da, sorgu u lara geilen parametrelerin isimli parametreler (named parameter) olabilmec sidir. Mesel ustteki rnekte description adl enin deerini ismiyle vermi a o og g s olduk, altta grdumz gibi: o ug u
query.setString("description", "ornek description 1");

Kyasla, JDBC kullanlrken bir PreparedStatement hazrlanr ve bu nesneye geilen sorgu iinde parametrelerin yeri bo braklarak ? karakteri ile gerek c c s c parametre deerlerinin sonradan gelecei belirtilir. Bu parametrelerin deerleri g g g ? iaretinin srasna gre bir numarayla belirtilir. s o
statement.setString(1,deer); g statement.setInt(2,200);

JDBC teknolojisinin bu tekniinin kod idaresi bakmndan kt bir yaklam g ou s olduu aktr, unk bir sre getikten sonra koda bakan programc iin 1,2,3 g c c u u c c gibi numaralar bir anlam ifade etmez (Kural #4). Bu numaralarn hangi parametreye ait olduunu anlamak iin sorguya tekrar bakmak ve soru iaretlerini teker g c s teker saymak gerekecektir. Daha kt bir senaryoda, yeni programc, sorgudaki ou parametrelerin srasn bir ekilde deitirir ve set komutlarn gncellemeyi uns gs u utursa, uygulamamza birdenbire yeni bir hata (bug) eklenmi olacaktr. Kural s #1: Her zaman bakm klfeti en az olacak metotu seiniz. Bu adan HQLin u c c parametre gei yntemi tercih edilir olmaktadr. cs o

2.6.4

Guruplama Teknikleri

Kurumsal uygulamalarda kullanlan sorgulama dillerinin olmazsa olmaz zellii o g guruplama zelliidir (SQL dilinde ska kullandmz SUM, AVG, MAX ve GROUP o g c g BY gibi komutlar, bu tr guruplama fonksiyonlardr). HQL, aynen SQL gibi, guu ruplamay desteklemektedir. Mesel alttaki gibi bir Person elemesi olduunu a s g farz edelim, ve bu eleme uzerinden baz guruplama tekniklerini grelim. s o
<hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <import class="org.mycompany.kitapdemo.dao.Summary"/> <class name="Person" table="person"> <id name="lastName" column="lastname"> <generator class="assigned"/> </id> <property name="name" column="name"/> <property name="age" column="age"/> </class>

32

Sorgular
</hibernate-mapping>

Eer tm PERSON.AGE toplamlarn almak istersek g u


Session s = HibernateSession.openSession(); String hql = select sum(person.age) from Person person; Integer ageSum = (Integer)(s.createQuery(hql)).uniqueResult();

sorgusunu kullanabiliriz. En ust deer (maximum) bulmak iin, max kullanlr. g c


Session s = HibernateSession.openSession(); String hql = select max(person.age) from Person person; Integer ageSum = (Integer)(s.createQuery(hql)).uniqueResult();

2.6.5

SQL ile Sorgulamak

Hibernate ile sorgulamak iin, HQL yerine direk SQL de kullanabilirsiniz. c Bizim tavsiyemiz, ou zaman daha gcl ve ksa olan HQL dilini kullanmanz c g u u ynndedir. Sadece ve sadece baz durumlarda uretilen SQLin yerine elle SQL o u yazmak isterseniz, Hibernatein createSQLQuery ve addEntity komutlar ile direk SQL iletebilirsiniz. s Hibernate uzerinden SQL iletince geriye dnecek deerler JDBC Result s o g set yerine List iinde POJOlar olarak alabiliriz. Bunu yapmak iin SQLe tek c c eklemeniz gereken, dondrlecek tablo ismi etrafnda { } iaretleri ve SQLQuery uu s nesnesi uzerinde addEntity arsdr. Mesel, c g a
select garage.* from Garage garage where garage.description like %garage%

gibi bir SQL, una dnecektir: s o us


Query query = s.createSQLQuery( "select {garage.*} from Garage garage " + "where garage.description like %garage% " ) .addEntity("garage", Garage.class);

Grldu gibi garage tablosunun tm kolonlarn dndrmek istiyoruz, bunun o u ug u o u iin garage.* ibaresini kullandk. Bu normal SQLdir. Buna ek olarak, garage c .* etrafna { } ekleyerek, geri dnen deerlerin Hibernate POJOlar olduunu o g g bildirmi oluyoruz. Ayrca createSQLQuery arsndan geri gelen SQLQuery s c g nesnesi uzerinde hangi POJOyu geri almak istediimizi belirtmemiz gerekiyor. g Bu belirtildikten sonra Hibernate, JDBCden gelen Resultset uzerindeki kolon lar zaten elinde olan eleme dosyalar uzerinden dntrerek, biz nesnesel s o us u programclarn sevdii bir nesne listesi olarak sonucu almamz salayacaktr. g g

2.6.6

Deiik Nesnelerden Tek Sonu Listesi gs c

Simdiye kadar grdumz sorgulama tekniklerinde, sonucu sadece Hibernate o ug u tarafndan elenmi bir nesne ya da nesneler iin almay grdk. Fakat bazen s s c o u 33

2. Hibernate uygulamamzda farkl nesnelerden gelen eleri Hibernatete elenmemi bir og s s birimin listesi olarak sunmamz gerekebilir. SQL ile bunu
SELECT t1.kolon1, t2.kolon1, t3.kolon1, ... FROM TABLO1 t1, TABLO2 t2, ...

eklinde bir kullanm ile yapyoruz. Sonu listesinin iindeki kolonlar oradan, s c c buradan toplanyor. Acaba HQL, aynen SQL gibi farkl nesnelerden (tablolardan) toplanm eleri (kolonlar) tek bir sonu listesi olarak sunamaz myd? s og c Evet bunu yapmak mmkndr. SQLe benzer bir ekilde, u u u s
select garage.description, car.description, person.age from Garage garage left join garage.cars car left join garage.cars.person person where ...

gibi bir kullanm, bize bir java.util.List iinde Object[] nesneleri dndrec o u cektir. Object[] iindeki her eleman, HQL select listesinde belirtilen e c og isimlerinden bir tanesi olacaktr. Daha Iyisi Fakat Object[] uzerinden indis kullanarak eriim, hatrlamas ve bakm zor s bir yntemdir. Bu sebeple daha idare edilir bir yntem olarak bir ara nesne o o kullanma yntemi tercih edilir. Geici ara nesne kullanmnda, kurucu metotu o c sadece bizim beklediimiz eleri alan bir ara class yazlr. Orneimiz iin bu g og g c class ismi Summary olsun. Liste 2.7: Summary.java
package org.mycompany.kitapdemo.dao; public class Summary { public Summary(String garageDesc, String carDesc, Integer age) { this.garageDesc = garageDesc; this.carDesc = carDesc; this.age = age; } String garageDesc; public String getGarageDesc() { return garageDesc; } public void setGarageDesc(String newGarageDesc) { this.garageDesc = newGarageDesc; }

34

Sorgular

String carDesc; public String getCarDesc() { return carDesc; } public void setCarDesc(String newCarDesc) { this.carDesc = newCarDesc; } Integer age; public Integer getAge() { return age; } public void setAge(Integer newAge) { this.age = newAge; } }

Bu ara nesneyi kullanan HQL sorgumuz u ekilde deiecektir. s s gs


select new Summary(garage.description, car.description, person.age) from Garage garage left join garage.cars car left join garage.cars.person person ...

Bylece sorgudan geri gelen java.util.List iinde Object[] yerine, java. o c util.List iinde Summary nesneleri alnabilecektir. c

Import Summary Hibernate tarafndan elenen bir class olmad iin, HQLin bu class s g c grmesi iin eleme dosyasna dahil edilmesi gerekecek. Dahil etme (import) o c s ilemini, SELECT listenizde referans edilen herhangi bir classn hbm.xml dosyasnda s
<hibernate-mapping ... <import class="org.mycompany.kitapdemo.dao.Summary"/> <class name=....>

gibi bir kullanm ile yapabilirsiniz. Ornek kod iin HibernateQueries projesine c baknz. 35

2. Hibernate

2.7

Otomatik Sema Uretimi

Eer gelitirme amal olarak, uygulama her baladnda uygulama tarafndan g s c s g Hibernate eleme dosyalar baz alnarak veri tabannda bir ema uretilsin iss s tiyorsak, o zaman hibernate.cfg.xml dosyasnda
<property name="hibernate.hbm2ddl.auto">update</property>

ibaresini kullanmak yeterlidir. Hibernatein eleme dosyalarndan ema uretes s bilmesi artc gelebilir; Fakat biraz dunlrse, Hibernatein bu ii yapmak s s us u u s iin elinde tm bilgilerin bulunduu anlalacaktr. Gelitirme amal olarak c u g s s c bu uretimin uygulama her balatldnda yaplmas baz uygulamalar iin kul s g c lanldr. Fakat sonu ortamndaki (production) tablolarn her balangta s c s c kaybetmek istemeyen (ya da hangi tablo ekleme komutlarnn uretildiini kon g trolden geirmek isteyen) ou kurumsal uygulama iin bu zellik pek yararl c c g c o olmayacaktr. Eer veri emasnn direk veri tabanna verilmesi yerine bir metin dosyasna g s yazlmas daha uygun ise, Hibernate (DROP TABLE, CREATE TABLE komutlarn ieren bir script uretme yeteneine de sahiptir. Bunun iin komut satrndan c g c SchemaExport adl Hibernate classn kullanabiliriz (classn kodlar hibernate3.jar iindedir). Kullanm iin; c c
java -Dhibernate.dialect=net.sf.hibernate.dialect.OracleDialect -cp \ /lib/cglib-full-2.0.2.jar;HIBERNATE_LIB/lib/odmg-3.0.jar;\ HIBERNATE_LIB/eg;HIBERNATE_LIB/lib/jboss-common.jar;\ HIBERNATE_LIB/lib/commons-collections-2.1.1.jar;\ HIBERNATE_LIB/lib/xerces-2.4.0.jar;HIBERNATE_LIB/lib/xml-apis.jar;\ c:/archive/kod/kitapkod/Struts/StrutsHibAdv/build/WEB-INF/classes;\ HIBERNATE_LIB/lib/dom4j-1.4.jar;HIBERNATE_LIB/hibernate3.jar;\ HIBERNATE_LIB/lib/log4j-1.2.8.jar;\ HIBERNATE_LIB/lib/commons-logging-1.0.4.jar \ org.hibernate.tool.hbm2ddl.SchemaExport --output=schema.sql --text \ HIBERNATE_LIB/eg/org/hibernate/auction/AuctionItem.hbm.xml \ HIBERNATE_LIB/eg/org/hibernate/auction/Bid.hbm.xml \ HIBERNATE_LIB/eg/org/hibernate/auction/User.hbm.xml

Hangi dialecti kullanld -D parametresi ile verilmelidir. g Classpath, -cp seenei ile tm gereken Hibernate jarlar iermelidir. c g u c Sema uretimi iin baz alnacak tm hbm.xml dosyalar, en sonda ve c u aralarnda boluk olacak sekilde sralanmaldr. Ornek kullanmda His bernate datm dizini altnda yer alan rnek kodlarn eleme dosyalar g o s kullanlmtr. Eleme dosyalarnn olduu dizinler iza (relative) olarak s s g deil, kesin (full) olarak verilmelidir. g Sema DDL kt dosyasn --output seenei ile belirtebiliriz. c c g 36

Middlegen --text secenegi ile sadece dosyaya yazlmasn istediimizi belirtebiliyg oruz. Eer SchemaExport yerine SchemaUpdate kullanrsak, bu komut bir nceki g o ema ve mevcut eleme dosyalar uzerinden uretilecek olan ema arasndaki s s s fark bularak, sadece o farklar iin gerekli ALTER TABLE komutlarn bir metin c dosyasnda uretecektir. Bu dosya teknik lider tarafndan kontrol edilip belki bir test ema uzerinde denendikten sonra sonu ortamna gnderilebilir, unk eks c o c u leme amal ALTER komutlar mevcut dier kolonlarn iindeki veriye zarar verc g c meyecektir.

2.8

Middlegen

Bir projenin banda, eer projenin kullanabilecei bir veri taban emas mevcut s g g s deil ise, bu emay tanmlamak projenin grevidir. Fakat bazen, bir ema g s o s zaten mevcuttur ve uygulamamzn mevcut emay kullanmas gerekiyordur. s Hi sorun deil: Mevcut tablolar iin Hibernate eleme dosyalarn, ve POJO c g c s kodlarn elle yazarz ve Hibernate uzerinden emaya erimeye balarz. s s s Fakat eer mevcut emada bulunan tablo says ok fazla ise, her tablo iin g s c c bir POJOyu elle yazmak klfetli bir ilem olabilir. Programcya bu konuda u s rahatlk salamak iin, Middlegen ad verilen bir ara salanmtr. Middlegen g c c g s ile, emanza balanp POJO kodlarn ve eleme hbm.xml dosyalarn otomatik s g s olarak urettirebilirsiniz. Middlegen (retim amacyla) bir ema iinde aadaki u s c s g kalemlere bakar. Kolon, tablo isimleri Kolon tipleri Tablolar arasndaki yabanc anahtar ilikileri (foreign key constraints) s g Yni Middlegen kod uretmek iin ema meta verisini kullanr. Oe tipleri a c s iin, kolon tipine en yakn Java tiplerini kullanlmaya allr: Mesel VARc c s a CHAR kolon iin java.lang.String kullanmak gibi. Ayrca Middlegen, yac banc anahtar ilikilerini, POJOlar aras <many-to-one>, <set> gibi ilikilere s s evirmeye uraacaktr. c g s Bu uretim yapldktan sonra, uretilen kodlar projenize kopyalayarak, ustne u gereken eklemeleri yapp devam edebilirsiniz.

2.8.1

Felse Tavsiye

Kod uretim tekniini, eer gerekiyorsa, sadece bir kez ve bir balang noktas g g s c oluturmas amac ile kullanmalyz. Hibernate eleme dili, herhangi bir uretim s s teknolojisinin uretebileceinden ok daha gcldr. Hibernate eleme yapsnda g c u u u s 37

2. Hibernate envai trden ilikilendirme yntemi olduu gibi, performans amal optimizasyu s o g c onlar, ksm ksm ykleme (batch fetching), sonradan ykleme (lazy loading) u u gibi birok ayarlar vardr. Tm bu ayarlar sadece veri tabanna bakarak uretc u mek neredeyse imkanszdr. Ayrca Middlegen ile kod uretim tavsiyemiz, Kural #5 ihlli olarak alglanmamaldr. a POJO ve eleme dosya uretimini sadece bir ema mevcut olduu zamanlar s s g iin tavsiye ediyoruz. Ayrca uretimin verdii eleme dosyalar nal deildir, c g s g sadece bir tahminden ibarettir. Uretilen kod projeniz iin uygun olmayabilir. c Sadece bir balang noktas oluturmas asndan nemlidir, ve en azndan s c s c o dz, bir kolon bir e eklindeki elemeleri yapmas asndan faydal olau og s s c caktr.

2.8.2

Kullanmak

Middlegen iin en son srm Middlegen-Hibernate-r5 srmdr. Bu srm c uu uu u u uu tarafmzdan Hibernate 3.0a uyumlu hle getirilerek yeni bir srm oluturulmutur. a uu s s Kitap kodlar (Ek A iinde anlatld gibi) bulabileceiniz bu proje, kitap- c g g tools-middlegen-x.x.zip dosyasndaki Middlegen-Hib-r5-mycompany projesidir. Internette bulunan versiyon yerine, bu versiyonu kullannz. Middlegen-Hib-r5-mycompany projesi, localhostta alan ve bir MySQL c s uzerinde tutulan cars adl veri tabann kullanmak uzere hazrlanmtr. Eer s g deiik bir taban kullanmak istiyorsanz, ncelikle build.xml iindeki taban gs o c ayar dosyas ismini deitirin. gs
<!DOCTYPE project [ <!ENTITY database SYSTEM "file:./config/database/mysql.xml"> ]>

Eer mysql.xml yerine oracle.xml koyarsanz, config/database/oracle. g xml ayar dosyas kullanlacaktr. Tm mevcut taban ayar dosyalar iin conu c fig/database altna bakabilirsiniz. Ayar dosyalarnn iinde hangi taban, hangi kullanc ve ifre kullanld c s g gibi ayarlar vardr. Mesel MySQL iin taban ismini deitirmek isterseniz, a c gs config/database/mysql.xml iinde bu deiiklikleri yapabilirsiniz. Alttaki c gs ayarlar, localhost uzerindeki cars veri tabanna kullanc root ve bo ifre s s ile balanmak iin hazrlanmtr. g c s
<property name="database.script.file" value="\${src.dir}/sql/\${name}-mysql.sql"/> <property name="database.driver.file" value="\${lib.dir}/mysql-connector-java-3.0.9-stable-bin.jar"/> <property name="database.driver.classpath" value="\${database.driver.file}"/> <property name="database.driver" value="com.mysql.jdbc.Driver"/> <property name="database.url" value="jdbc:mysql://localhost/cars"/>

38

Middlegen
<property name="database.userid" value="root"/> <property name="database.password" value=""/> <property name="database.schema" value=""/> <property name="database.catalog" value=""/> <property name="jboss.datasource.mapping" value="mySQL"/>

Uretilecek kodlarn gidecei dizini ve POJOlarn paket ismini belirlemek g iin, build.properties iindeki pojo.package deikenine paket ismi veriniz. c c gs Orneklerimizde bu isim, org.mycompany.kitapdemo.pojo ismi olmutur. s

2.8.3

Test Sema

Simdi StrutsHibAdv projesine girerek, src/sql/tables_mysql.sql dosyasn MySQL tabannz uzerinde iletin. Bu ema iinde, yabanc anahtarlar ve kolon s s c ilikileri detayl bir ekilde hazrlanmtr, ve Middlegen bu ilikileri takip eds s s s erek kod uretimini yapabilecektir. Bu ema, altta gsterilmitir. s o s
DROP TABLE IF EXISTS garage; CREATE TABLE garage ( id numeric(30) not null, description varchar(30) , PRIMARY KEY(id), INDEX (id) ) TYPE = InnoDB; DROP TABLE IF EXISTS car; CREATE TABLE car ( version int(10) not null, license_plate varchar(30) , description varchar(30) , available int(1) , car_size varchar(1) , garage_id numeric(30), PRIMARY KEY(license_plate), INDEX (license_plate), INDEX (garage_id), FOREIGN KEY (garage_id) REFERENCES garage(id) ) TYPE = InnoDB;

Niye TYPE = MyISAM yerine TYPE = InnoDB kullanlmtr? Cunk MySQL s u tabanlarnda, kolonlararas iliki (foreign key constraint) kurmak MyISAM depos lama tipinde mmkn deildir. Bu konu detaylar iin 9.1.1 blmne bavurabilirsiniz. u u g c ou u s 39

2. Hibernate Sema hazrlandktan ve Middlegen ayarlar tamamlandktan sonra komut satrnda (Middlegen-Hib-r5-mycompany dizininde) ant komutunu iletebilirsiniz. s Bu komut sonucunda, 2.6 eklindeki gibi bir ekran ortaya kacaktr. s c

Sekil 2.6: Middlegen Ekran Bu ekranda Car ve Garage nesnelerinin ve nesneler arasndaki ilikilerin s tabandaki kolonlararas ilikiden hareketle alglanarak gsterilmi olacaktr. s o s Ekrandaki her nesne, ve o nesnedeki her e tklanabilir durumdadr. og Bir tklama ile, o nesne ya da e hakkndaki detaylar ekrann altnda greog o bilirsiniz. Eer bu detaylarda beenmediiniz bir durum varsa, deiiklii grsel g g g gs g o ara uzerinden yapmanz mmkndr. Iki POJO arasndaki iliki ynn bile c u u u s o u u bu grsel aratan deitirmeniz mmkndr: SHIFT ve mouseun sol dmesine o c gs u u u ug ile iliki uzerine tklarsanz, iliki yn deitirecektir. s s o gs Istediiniz tm deiiklikler tamamlandktan (ya da, herey uygun gzkyorsa, g u gs s o u u hibir deiiklik yapmadan) sonra, ekrann sol ust kesindeki Generate dmesine c gs os ug basarak nal kodu uretebilirsiniz. Uretilen kod nereye gider? Eer pojo.pack g age deikeni iin org.mycompany.kitapdemo.pojo tanmland ise, eleme dosyalar, gs c s build/gen-src/org/mycompany/kitapdemo/pojo altna atlacaktr. Son olarak, POJO Java kodlarn uretmek iin c
ant hbm2java

komutunu kullann. Bu ilem, aynen eleme dosyas uretiminde olduu gibi s s g build/gen-src/org/mycompany/kitapdemo/pojo altnda java dosyalarn yaratr. 40

OZET Uretim bittikten sonra bu dizin altnda Car.java ve Garage.java adndaki Java dosyalarn bulabilirsiniz.

2.9

Ozet

Bu blmde, veri nesneleri POJOlar ile veri tabanndaki tablolalar birbirine ou balayan, bize SQLe benzer bir dil ile sorgu yapmamz salayan, ve sonular g g c POJO listeleri olarak dnebilen Hibernate teknolojisini iledik. Hibernate, her o s tablo iin drt ilem olarak bilinen INSERT, DELETE, UPDATE, SELECT komutc o s larn ureterek bizi byk kod yazma klfetinden kurtarmaktadr. Ayrca, hi u u u c ek kod yazmadan ticari ya da ak yazlm nbellek paketlerine entegre olac o bilmesi sayesinde, Hibernate, nbelleklemeyi programc tarafndan elle yaplan o bir ilem olmaktan karmaktadr. Tablolar aras her trl ilikinin Hibers c u u s nate dnyasnda nesnesel karlklar vardr; Veri tabannda bire bir, bire ok, u s c oka ok trnden tm ilikiler, nesne dnyasnda bir nesneden dierine sanki c c uu u s u g herey hafzada oluyormu gibi takip edilebilmektedir. Nesnesel programclk s s dnyasnda bu ileme nesne haritasn gezmek (traversing the object graph) u s denir. Her nesne iin yaplan esi/kolon elemesi haricindeki tm Hibernate ayarlar, c og s u hibernate.cfg.xml adl dosyadan verilir: Onbellek, veri taban balant havuzunu g eleme dosyalarnn yerleri programc tarafndan burada tanmlanmaldr. s Hibernate, SQL benzeri, ama daha esnek ve gl olan HQL adl bir sorgu uc u dilini destekler. Bu sorgularn sonular, nesne listeleri olarak Hibernate tarafndan c annda evirilerek programcya sunulur. c Middlegen, mevcut emalardan Hibernate eleme dosyas ve POJO kodlar s s uretmek iin kullanlr. c Son olarak, Hibernatein ileyiini hzlandrmak, leklemek iin, 5.4.4, 5.4.5, s s oc c 5.4.6, ve 5.4.7 blmlerine, Hibernate kodlarmz JUnit ile birim testlerinden ou geirmek iin ise, 7.1.3 blmne bakabiliriz. c c ou u

41

2. Hibernate

42

Bl m 3 ou

Web Uygulamalar

Bu Bl mdekiler ou Bir Web projesinin gelitirme ve hedef ortamn kurmak s iin gerekenler c Trke karakter destei ve ulusallatrma u c g s Struts ve JSTL Etiketleri Genel Web ihtiyalari ve zmleri c co u

43

3. Web Uygulamalar

yn anda birok kullancya hizmet verebilen servis taraf Web teknolojic leri, ve dinamik ierik gstermek iin kullanlan Web sayfas etiket dilleri c o c u anki hline gelmek iin uzun bir evrimden geti. Dinamik ierik, ilk s a c c c nesilde, Perl, sh, bash, C gibi dillerle yazlm, Apache Web Server tarafndan s iler kod olarak arlan CGI programlar tarafndan uretiliyordu. s c g Java dnyas, CGI yerine pr Java Uygulama Servisleri tarafndan arlabilen u u c g Java Servletleri yerletirdi, ve ierik gstermek iin de JSP adl etiket dilini s c o c bize sundu. Bu ilk nesilde, grsel olmayan ilemleri dahi Servlet yerine grsel o s o amal yazlm JSPlerden yapmak mmkn oluyordu, ki bu tr kullanma c s u u u Model I ismi de verilmitir. Fakat Model I, aksiyon JSPleri ile ierik JSPlerini s c birbirinden ayrmayarak bakm zor mimarilere sebebiyet verdii iin, bir sre g c u sonra Model IIye geilmitir. c s Model II, aksiyonlar (veri tabanndan bilgi almak, hata kontrol gibi ilemler) u s iin ayr JSPler yazlmasn ngryordu. Fakat bu mimariden de hlen eksik c o ou a olan faktr, mesel bir HTML formundan bilgi almak, kullancnn taraycsn o a baar ya da hata sonras bir sayfaya gnderebilmek gibi ilemler iin salanmas s o s c g gereken altyap hizmetleri idi, ve bu ilemler JSP (ya da Servlet) iinden Java s c kodu yazlarak programcya zahmet getiren bir ekilde yaplmas gerekiyordu. s

3.1

MVC

Bunun uzerine daha nce masast grsel programlar iin baaryla kullanlm o u u o c s s MVC mimari ekli Web dnyasna uyarlanmaya baland. MVC mimarileri ve s u s urnleri, grsel bir program uc ana blme ayrp her blme ayr altyap u o ou ou kodlar ve hizmetleri salayarak bakm kolay kodlar yazmamza yardm eden g mimarilerdir. MVC programnn ana blmleri unlardr: ou s Model View Controller Model, hakknda program yazdmz i alann hakkndaki kurallar, hesaplar g s yaptrdmz alan modelini temsil eden nesnelerdir. Mesel kurumsal prog a gramnz yazdnz irket (mteriniz) araba kiralama hizmeti veren bir irket g s us s olsayd, bu program iinde Car nesnesi, modelin paras olurdu. c c View, grsel ilevleri yerine getiren kodlardr. Ekrana bilgi gstermek iin o s o c yaplan tm arlarn toplam MVCnin Vsini (View) oluturacaktr. u c g s Controller, yni kontrolcu, grsel programnzn akn, hangi sayfadan a o s sonra hangi sayfaya, hatalardan sonra hangi grsel birime ynlendirileceini o o g kontrol eden ksmdr. Bu birime ynlendirici, ya da trak polisi ismi de vero ilebilirdi. 44

Ana Kavramlar Java dnyasnda MVC mimarisini destekleyen birok urn mecuttur. Bu u c u urnlerden en tannm ve stabil hlde olan, Apache projesi tarafndan sunulan u s a Struts projesidir.

3.2

Ana Kavramlar

Grsel Web mimarilerinde ok sk lazm olan kalplar, Apache Struts tarafndan o c MVC altyaps erevesine koyularak, Jakarta Struts projesi oluturuldu. Modc c s ern Web uygulamalarnda ok ihtiya duyulan kodlama gereklilikleri unlard: c c s Giri yaplan Web sayfalarndan, yani Formlardan, veri alp vermeyi ras hatlatrmak. s JSPde bir dme (button) bas hareketine tekabl eden bir ilemi, ug s u s tekrar kullanlr (reusable) bir nesne iinde muhafaza etmek, ve bir Web c uygulamasn artk bu ilemlerin (action) biraraya konulduu bir btn s g uu olarak grmek. o Sayfalar aras ak tanmlarn (ow) Servletlerin, yani Java kodunun, s iinden kurtarp bir ayar dosyas iinde tutmak, bylece ak deitirmeyi c c o s gs kolaylatrmak. Ayrca bu sayede ak iindeki ilemleri de daha rahat s s c s tekrar kullanlr hale getirmek.

3.2.1

Form ve Action

Sekil 3.1: Request, Response ve Struts Action Bir Struts projesi struts-config.xml denen ayar dosyas etrafnda dner. o Bu dosya, u ekilde tanmlar ierir. s s c 45

3. Web Uygulamalar
<form-beans> <form-bean name="AddCarForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="licensePlate" type="java.lang.String" initial=""/> <form-property name="description" type="java.lang.String" initial=""/> </form-bean> </form-beans> <action-mappings> <action path="/main" scope="session" type="org.mycompany.kitapdemo.actions.GetCarsAction"> <forward name="fail" path="/pages/main.jsp"/> <forward name="success" path="/pages/main.jsp"/> </action> <action path="/add-car" scope="session" type="org.mycompany.kitapdemo.actions.AddCarAction" name="AddCarForm" validate="false"> <forward name="success" path="/main.do"/> <forward name="fail" path="/main.do"/> </action> </action-mappings>

Iki tanm herhalde hemen gznze arpmtr. Biri AddCarForm, teki Ado u u c s o dCarAction. Struts kodu yazarken, ya bir JSP, ya bir Form, ya da bir Action yazyoruzdur. Form, tahmin edilecei gibi veri girilen bir Form sayfasnn g uzerindeki deerleri tutan bir Java Bean nesnesidir. Uzerinde sadece get, set, g reset, ya da validate gibi metotlar vardr. Strutsn salad nemli bir rag g o hatlk, zel etiketler uzerinden sayfanzdaki alanlar bu Beane otomatik olarak o balamak olacaktr. Sayfadaki alan deiince bu beandeki elenmi olan deer g gs s s g de deiecektir. Bylece Java sunucu tarafndaki kodlarnz get/set kullanarak gs o sayfa verilerine eriebilmi olur. Hatt en son Struts versiyonlarnda, uzerinde s s a get/set metotlar olan ayr bir beane bile ihtiyacmz kalmamstr; Artk bu bean Struts DynaActionForm kullanm sayesinde dinamik olarak uretilebilmek tedir. 46

Ana Kavramlar Action (ilem) ise, bir dmeye bastmzda yaplmas gereken ilemi kods ug g s ladmz yerdir. O da bir Java nesnesidir, ve JSP sayfas iinde (struts-cong c fig.xmlde tanmlanan ismi uzerinden) carlmas gerekir. g Carlmas kelimesi tabii Struts iin tam uygun bir kelime deildir. Say g c g fadaki dmeler ile Actionlar, struts-config.xml iinde elenir demek ug c s daha uygun olur. Cunk rma ileminin kendisini Struts mimarisi kapal u cag s kaplar arkasnda yapmaktadr. JSP sayfasnda bir dme ile Action elemek yle olur. ug s so
<html:form action="/add-car.do"> ... <td> <html:submit>Araba Ekle</html:submit> </td> </html:form>

add-car.do balants ise, sonunda .do kelimesi ierdii iin bir Struts Acg c g c tion balantsdr. Struts projenizi kurduunuzda Web Sunucunuza (Tomcat, g g Weblogic, JBoss) verdiiniz web.xml ierisinde, .do adl soneki, Struts ana g c ilemci Servletine balanmas gerektiini Web Sunucusuna belirtmemiz gereks g g mektedir. Proje baznda tm Actionlar iin bir kere yaplmas yeterli olan u c bu tanm merak edenler, rnek uygulamamzda web.xml iine bakabilirler; o c Aadaki trden bir ibare greceklerdir. s g u o
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> ... </servlet>

3.2.2

JSP ve Form Balantlar g

Struts altyaps, Formlara otomatik deer aktarabilmek (ve daha baka grsel g s o amalar iin de) zel Struts etiketleri salar. Yni bir Struts projesinde JSP c c o g a yazarken bildiimiz jsp:bean trnden etiketler deil, Struts html:text gibi g uu g etiketler kullanacaz. Mesel, sayfamza bir metin (text) alan koyup, bu alan, g a Form beani uzerindeki bir alana balamak istesek, g
<html:text property=licensePlate/>

gibi bir ifade kullanmamz gerekir. licensePlate (plaka) ad ile belirtilen bu metin giri alan ekteki rnek kodlarda AddCarForm nesnesi uzerindeki getLis o censePlate, setLicensePlate metotlarna elenecektir. Yani, Struts altyaps s 47

3. Web Uygulamalar tarafnda arlacaktr. (Tabii DynaActionForm kullanm var ise, get/set ieren c g c beanin varlna bile gerek yoktur, dinamik AddCarForm nesnesinin get/set g metotlar dinamik olarak arlacaktr). c g Dikkat edelim, get ve setin ikisinin birden Struts tarafndan arlacandan c g g / kullanlacandan bahsettim. Struts, Form beanine sadece tek bir zamanda g deer aktarmaz. Deer aktarm ters yn iinde geerlidir, yani, arka planda g g o c c Java uzerinden Formda deiiklik yapp bir sayfaya tekrar dndgnzde, say gs o u u u fadaki deerin de deitiini greceksiniz. g gs g o ComboBox, Radio Button gibi grsel birimlerin ayr ayr html: kullanm o vardr.

3.2.3

Actionlardan Sonra Ynlendirme o

Strutsn ustlendii nemli dier bir grevde, uygulamanz iin trak polislii g o g o c g grevidir. Normal Java web uygulamalarnda bir Servletten teki Servlete o o aktarm redirect ars ile yapyorduk. Fakat bu yntem sonraki sayfa ismini c g o direk JSP iine gmmesi sebebiyle kod muhafazas ve bakm asndan iyi bir c o c yntem deildir. o g Struts mimarisi, ynlendirme tanmlarn Java kodu ierisinden kartarak o c c bir ayar dosyasna koyarak deitirilmesini rahatlatm, ve bu ekilde Java kodgs s s larnn daha temiz ve modler olmasn salamtr. u g s Mesela rnek uygulamamzda AddCarAction ilendikten sonra dier bir Aco s g tion olan get-cars.doya gitmek istesek, bunun iin Java kodu yazmamza c gerek yoktur. struts-config.xml iinde, AddCarAction tanm altnda, bu c yn belirtmemiz yeterlidir. Struts Action class sadece ve sadece bir duo u rum kodu dndrmekle ykmldr. Bu durum koduna bal olarak nereye o u u u u u g gidileceinin kararn struts-config.xml dosyas verecektir. Ornek Action g tanmmzdaki
<action path="/add-car" .. <forward name="success" path="/main.do"/> <forward name="fail" path="/main.do"/>

kullanm, success durum kodu dndrldunde /main.do, hata dndrldunde o u u ug o u u ug de yine /main.doya gidilmesini belirtmitir (durum kodu fail iin gidiles c cek yer deiik bir yer de olabilirdi. Bu tanm programcya ait bir seimdir. gs c Genellikle ekleme ekranlarndaki hatalar ayn sayfada gsterek iyi olduu iin o g c bu yntem seilmitir). main.donun kendisi de nihai olarak bir JSP sayfasn o c s gsterecektir, bylece Controller (Action) aamasndan sonra View aamasna o o s s geldiimizi gryoruz. g ou
<action path="/main" scope="session"

48

Ana Kavramlar
.. <forward name="fail" path="/pages/main.jsp"/> <forward name="success" path="/pages/main.jsp"/> </action>

3.2.4

Action Zincirleme

Struts teknolojisinin Action ve ynlendirme yetenei sayesinde kullancnn o g tklamas ve bir View ieren (sayfa) gelmesi arasnda birka tane Actionn zinc c cirleme bir ekilde iletilmesi bile mmkndr. Modler tasarm asndan bunu s s u u u u c yapmak faydal da olabilir. Struts projelerinizde lanca aksiyona ihtiya duyup c ta ah byle bir Action zten baka bir tarafndan yazlm, onu kullanaym o a s s diyerek o mevcut Action zincire kattmz ok olmutur. Bu, Strutsn MVC g c s modler altyaps sayesinde tekrar kullanlabilir Actionlarn yazlabilmesi sayesinde u olmutur. Yeni bir Action zincire katmak, Java kodlamas gerektirmedii iin, s g c struts-config.xml seviyesinde yaplan deiiklikler yeterli olacaktr. gs Mesel, elimizde GetGaragesList adnda tm garajlarn listesini alp web a u oturumu uzerinde garageList deikeniyle depolayan bir Action olsun. Bu ac gs tion, normlde garage-list.do adnda garajlar listeleyen bir sayfa garages a .jsp iin kullanlmaktadr. struts-config.xml yledir. c so
<action path="/garage-list" scope="session" type="org.mycompany.kitapdemo.actions.GetGaragesAction" validate="false"> <forward name="success" path="/pages/garages.jsp"/> <forward name="fail" path="/pages/garages.jsp"/> </action>

Fakat diyelim ki, yeni bir sayfa yazyoruz. Bu newPage.jsp adnda yeni sayfa iin gsterilen bir takm dier eylere ek olarak, bir de garaj listesini bir seim c o g s c listesi (listbox) iinde gstermek gerekiyor. Garaj listesini nereden alacaz? c o g Yeni Action iinde bir daha garaj sorgulamas yapmak bir zm olabilir, fakat c co u buna gerek yok. Daha nce yazdmz GetGaragesAction kullanabiliriz ve o g yeni Actionmza zincirleyebiliriz.
<action path="/new-action" scope="session" type="org.mycompany.kitapdemo.actions.NewActionX"> <forward name="success" path="garage-list-for-x"/> <forward name="fail" path="/pages/error.jsp"/> </action> <action path="/garage-list-for-x"

49

3. Web Uygulamalar
scope="session" type="org.mycompany.kitapdemo.actions.GetGaragesAction" validate="false"> <forward name="success" path="/pages/newPage.jsp"/> <forward name="fail" path="/pages/newPage.jsp"/> </action>

3.2.5

Struts ve JSTL

Apache Struts, mimari adan MVCnin hem Controller, hem View tarafn c gerekletiren bir pakettir. Controller, unk Strutsn nemli bir hizmeti, akc s c u o siyon birimlerine ve ynlendirme ilemlerine bir altyap salamasdr. View, o s g unk Form nesneleri ve JSP arasnda kurulmu ilintiler sayesinde View taraf c u s iin de verilen hizmetler vardr. c Tek eksik, Strutsn etiketlerinin ok etrelli sunum stilleri bazen yeterc c siz kalmasdr. Mesela, bir URLi html:link ile dinamik olarak olutururken, s birden fazla URL parametresi kullanamamaktayz. Bu ve dier baz etkenler yznden, pr prezentasyon ihtiyalar iin kitabmzda g u u u c c Strutsn Controller ve Form hizmetlerinin ustne, pr prezentasyon amal u u c olarak JSTL adl etiket dilini kullanmay setik. JSTL, JSP Standart Etiket c Ktphanesi (JSP Standart Tag Library) kelimesinin ksaltlmdr. JSTL, eski uu s JSP dilinden ok daha gcl bir dil olarak yeni nesil etiket dillerine standart c u u getirmeyi amalamtr. Java dnyasndan standartlarn her zaman baarl c s u s olduu sylenemez, fakat JSTL iin ayrca bir referans gerekletirimi (refg o c c s erence implementation) saland iin ortada bir iler kod vardr, ve etiket g g c s dilinin temizlii tm bunlara eklenince ortaya Java Web dnyas iin tercih g u u c edilir bir seenek kmtr. c c s Bu sebeple, kitabmzdaki tm rneklerde, ve tavsiye ettiimiz mimari ve u o g urnsel yelpazede JSTLi bulacaksnz. u

3.3

Gelitirme Ortam s

Kitabmzdaki rnek Web kodlarn iletmek iin JBoss Uygulama Servisini o s c kullanacaz. JBossta bir web uygulamasn ileme koymak iin, JBOSS/deg s c fault/deploy dizini altna sonu kodlarn gndermek gerekir. Fakat bu, .class c o dosyalarn olduu gibi deploy dizini altna kopyalayabiliriz demek deildir. g g J2EE standartnn mecbur kld zel bir paketleme sistemini takip etmemiz g o gerekiyor. Bu paketleme eitleri unlardr: EAR, SAR ve WAR. c s s En ust seviye paket EAR paketidir. EARin iine SAR, SARn iine de c c WAR konur. Eer uygulamanzda EJB bileeni yok ise, sadece EAR ile uramadan g s g s direk SAR kullanabilirsiniz. Biz, Struts odakl tm rnek uygulamalarmzda u o SAR paketlemesini kullanacaz. g 50

GELISTIRME ORTAMI Onemli bir husus, ak paket vs. kapal paketleme konusudur. SAR, EAR c ve WAR, aynen JAR ynteminde olduu gibi sktrlm bir zip dosyas olao g s s bilirler. Biz bu yntem yerine, sktrlacak dosyalarn ak bir ekilde tuo s c s tulmasn setik. JBoss Uygulama Servisi, 3. versiyonundan itibaren, deploy c altnda grdu proje.sar dosyas ile proje.sar dizinini edeer tutmaktadr. o ug s g Yni, bir SAR iine zipleyerek koyacanz dosyalar bir SAR dizini altna kopya c g alarsanz, JBoss servisi uygulamanz fark gzetmeden ileme koyacaktr. o s Niye ak dizin yapsn setik? Cunk sonu (production) makinasna kod c c u c gnderirken baz ayar dosyalarnn o makina iin deimesi gerekiyor. Eer kao c gs g pal bir SAR, EAR, WAR dosyas gnderiyor olsaydk, bu dosyalarn iinde o c kalm olan ayar dosyalarn sonradan deitirmemiz mmkn olmazd. Tabii s gs u u ki her makina iin zel EAR, SAR, WAR derlemek mmkndr, fakat sonu orc o u u u c tam iin deiik derleme yapmak kesinlikle idare edilebilir bir yntem deildir. c gs o g Oncelikle her makina iin deiik olacak ayar dosyalarnn derleme sistemine c gs bildirilmesi gerekmektedir. Bu derleme sistemini daha kartracaktr. s Bu sebeple her makina iin gerekli ayar dosyalarn derleme ve kod gnderc o imden sonra EAR, SAR, WAR iinde deitirmek (eskisinin uzerine yazmak), c gs daha idare edilebilir bir yntem olmutur. En nemlisi, bu yntemi takip edo s o o erek sistem adminlerine ayar dosyalarn elle bile deitirme seeneini salam gs c g g s oluyoruz. Simdi, veri tabanna erien kurumsal bir Struts uygulamasn gelitirmek s s iin gereken gelitirme ve hedef dizin yaplarn grelim. Hedef Uygulama c s o Servisimiz JBoss 4.0.1, ve hedef dizinleri JBossun kurulu dizinin altnda alts taki gibi olacaktr.

3.3.1

Gelitirme Dizinleri s

+- StrutsHibSimple | +- build.properties | +- build.xml | | +- dd | | | +- jboss-service.xml | | | +- struts-config.xml | | | +- tiles-defs.xml | | | +- validation.xml | | | +- validator-rules.xml | | | +- web.xml | | | +- META-INF | | | | +- MANIFEST.MF | | | +- tags | | | | +- c-rt.tld | | | | +- c.tld | | | | +- fmt-rt.tld | | | | +- fmt.tld | | | | +- sql-rt.tld

51

3. Web Uygulamalar
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +- sql.tld | | +- struts-bean.tld | | +- struts-html.tld | | +- struts-logic.tld | | +- struts-nested.tld | | +- struts-tiles.tld | | +- x-rt.tld | | +- x.tld +- lib | +- c3p0-0.8.4.5.jar | ... | ... | +- cglib-full-2.0.2.jar | +- commons-beanutils.jar | +- hibernate3.jar | +- xml-apis.jar +- resources | +- application.properties | +- hibernate.cfg.xml | +- log4j.properties | +- log4j.xml | +- oscache.properties +- src | +- java | |+- org | | +- mycompany | | | +- kitapdemo | | | | +- actions | | | | | +- AddCarAction.java | | | | | +- GetCarsAction.java | | | +- dao | | | | +- Dao.java | | | +- pojo | | | | +- Car.hbm.xml | | | | +- Car.java | | | +- service | | | | +- AppStartup.java | | | | +- AppStartupMBean.java | | | | +- HibernateSession.java | | | +- util | | | | +- AllTest.java | | | | +- ClassPathFile.java | | | | +- RequestCharacterEncodingFilter.java | | | | +- TestUtil.java | +- pages | | +- detail.jsp | | +- main.jsp

52

GELISTIRME ORTAMI
| | | +- sql | | | | +- tables_mysql.sql

Bu gelitirme dizin yapsnda aranan dosyay bulmak olduka rahattr. En s c ust seviyede src/, resources/, dd/ ve lib/ dizinleri konulmutur. Eer yeni s g bir JBoss tanm XMLi konmak istense, bunun dd/ altna gidecei bellidir. g Ayn ekilde uygulamann kendi iinde kulland ayarlar iin properties ayar s c g c dosyalar ve dier XML bazl dosyalar resources/ altnda gene en ust seviyeg den eriilir hldedir. Kaynak dosya kategorisine giren her ey, src/ altndadr: s a s JSP sayfalar, Java kodlar ve SQL DDL komutlar gibi kalemler bu dizin altnda alt dizinler olarak bulunacaktr.

3.3.2

Hedef Dizinleri

Gelitirme dizininize gidip, komut satrndan ant komutunu ilettiinizde, JBOSS s s g /server/default/deploy altnda aadaki dizin yapsnn olutuunu gres g s g o ceksiniz.
+- kitapdemo.sar | +- META-INF | | | +- jboss-service.xml | | +- conf | | | +- log4j.xml | | +- kitapdemo.war | | | +- pages | | | | +- detail.jsp | | | | +- main.jsp | | | +- META-INF | | | | +- MANIFEST.MF | | | +- WEB-INF | | | | +- jboss-service.xml | | | | +- struts-config.xml | | | | +- tiles-defs.xml | | | | +- validation.xml | | | | +- validator-rules.xml | | | | +- web.xml | | | | +- classes | | | | | +- application.properties | | | | | +- hibernate.cfg.xml | | | | | +- log4j.properties | | | | | +- log4j.xml | | | | | +- oscache.properties | | | | | +- org | | | | | | +- mycompany | | | | | | | +- kitapdemo | | | | | | | | +- actions | | | | | | | | | +- AddCarAction.class | | | | | | | | | +- GetCarsAction.class | | | | | | | | +- dao

53

3. Web Uygulamalar
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +- Dao.class | | | | +- pojo | | | | | +- Car.hbm.xml | | | | | +- Car.class | | | | +- service | | | | | +- AppStartup.class | | | | | +- AppStartupMBean.class | | | | | +- HibernateSession.class | | | | +- util | | | | | +- AllTest.class | | | | | +- ClassPathFile.class | | | | | +- RequestCharacterEncodingFilter.class | | | | | +- TestUtil.class +- lib | +- activation.jar | +- ant-antlr-1.6.2.jar | +- antlr-2.7.4.jar | +- c3p0-0.8.4.5.jar | +- cglib-full-2.0.2.jar | +- commons-beanutils.jar | +- commons-codec-1.3.jar | ... | ... | +- standard.jar | +- struts.jar | +- xalan.jar | +- xml-apis.jar +- tags | +- c.tld | +- c-rt.tld | +- struts-html.tld

Bu yap JBoss tarafndan ileme konmaya hazrdr. Yap olarak, grldu gibi s o u ug WAR dizini, SAR dizini iine konmutur. c s

3.3.3

Web Ayar Dosyalar

Bir SAR paketi iine konulan ayar dosyalarn teker teker tanyalm. c jboss-service.xml Bir SAR paketi JBoss tarafndan yklenirken o proje iin yaplmas gereken u c hazrlklar, jboss-service.xml dosyasnda belirlenir. JBoss bu dosyay her zaman SAR paketinin META-INF dizini altnda arayacaktr. Bu dosyada, balatlmasn istediimiz MBean classlarn belirtmemiz gerekir s g (MBeanleri daha yakndan JMX ile ilgili 6.3.1. blmde tanyacaz). Bir ou g MBean, standart bir arayz (interface) gerekletiren (implement) bir Java u u c s 54

GELISTIRME ORTAMI classdr. Kendi yazdmz kod olabilecei gibi JBoss, ya da dier ak yazlm g g g c paketlerinden gelen bir MBean class da olabilir. StrutsHibSimple rneinde, Log4J paketinin baslang ilerinin yapan MBean o g c s nesnesinin, ve demomuzun kendi balang kodlarnn olduu AppStartup adl s c g MBeanin balatlmasn istedik. Bunlar yapmak iin gereken jboss-service s c .xml yle olacaktr. so Liste 3.1: jboss-service.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE server> <server> <!-- AppStartup adl class balang kodlarmz tayor. --> s c s <mbean code="org.mycompany.kitapdemo.service.AppStartup" name=":service=AppStartup"/> <!-- Log4J --> <mbean code="org.jboss.logging.Log4jService" name="jboss.system:type=KitapDemoLog4jService, service=KitapLogging"> <!-- Ayar dosyasnn yeri ve ismi. --> <attribute name="ConfigurationURL">resource:conf/log4j.xml </attribute> <attribute name="Log4jQuietMode">true</attribute> <!-- Ayar dosyasnn ne kadar sklkla kontrol edilecei --> g <attribute name="RefreshPeriod">60</attribute> </mbean> </server>

log4j.xml Log4j.xml, Log4J loglama sisteminin ayarlarn yapmak iin kullanlr. Aslnda, c bu ayar dosya ismi istee gre deiebilir; Hangi ismin kullanlacan jboss- g o gs g service.xml iinde resource:<dosya yeri, ismi> uzerinden belirtmek gerekc mektedir. Dosya yeri ve ismi, kitapdemo.sar referans alnarak aranacaktr. Orneimizde jboss-service.xml iinde conf/log4j.xml ayar kullanld iin, g c g c kitapdemo.sar/conf/log4.xml adl bir dosya aranacaktr. Ayar dosyas log 4j.xml iinde, hangi Java paketlerinin loglama yapabilecei, bu paketlerin c g hangi seviyede loglayaca (DEBUG, INFO, vs) ve mesajlarn yazld log dosyasnn g g hangi dizinde olduu gibi ayarlar belirlenir. g Demomuzun yapt log4j.xml ayarlar JBossun kendi ana Log4J ayarlar g ile (server/default/conf/log4j.xml altnda) uyumlu alacak ekilde yazlmtr. c s s s Bu kullanm ekli sayesinde, JBossun kendine zel dier loglama ilemleri hal s o g s a devam edecektir, fakat bunun ustne bizim uygulamamza zel loglar JBOSS u o /server/default/log/kitapdemo.log altna gider. Bu tr kullanm ou kuu c g rumsal uygulamann ihtiyac olan bir kullanm eklidir. Projelerde genelikle s 55

3. Web Uygulamalar JBossun kendi iinden gelen mesajlarnn bilinen bir log dosyasna (server c /default/log/server.log) gnderilmesini istenir. Ek olarak kendi uygulao mamzn loglar ayr bir dosyaya gitmesi beklenir. MANIFEST.MF Bu dosyann basmakalp bir ierii vardr. Ornek kodlarda greceiniz ierik c g o g c her proje iin ayn olacaktr. Olduu gibi kullanabilirsiniz. c g web.xml 3.2.1 blmnde grdumz gibi, web.xmlin bir Struts projesinde nemli ou u o ug u o grevlerinden biri Struts kullanmamz salayan ActionServlet adl merkezi o g class JBossa tantmaktr. Buna ek olarak Servlet ltreleri web.xml iinde c tanmlanr. Her uygulama iin Servlet ltresi gerekmeyebilir. Bizim uygulac mamzda JSP ve Action baznda Trke karakterleri destekleyebilmek iin Reu c c questCharacterEncodingFilter adl ltreyi web.xml iinde tanmladk. c Bunlarn haricinde, Struts bazl bir sistem web.xmle ihtiya duymayac caktr. Struts uygulamalarnda i mant Action nesnelerinde, ve dier tm s g g u Web odakl ayarlar (ak kontrol, hata muamelesi, vs) struts-config.xml s u ayar dosyasnda yapld iin, eski yntem Model I ve II uygulamalarnda g c o olduu kadar web.xml dosyasna ihtiya olmaz. g c

3.3.4

HibernateSessionCloseFilter

Hibernatei kapsaml olarak anlattmz 2. blmde veri taban ile iimiz bittiinde g ou s g bu durumu HibernateSession.commitTransaction() ve HibernateSession .closeSession() belirteceimizi sylemitik. Fakat bu ekildeki Session ve g o s s Transaction kullanm Web ortamnda problemler douruyor. g Problemin k noktas Struts Actionlar ve JSP sayfalarnn ieriklerini c s c gstermesinde olan ileyi srasdr. Eer elimizde Garage ve onun uzerinde o s s g bir set olarak tutulan Car nesneleri var ise, tipik olarak bir Struts Action ile bu listeyi alrz ve JSP ile sunum iin bir HttpSession uzerine koyarz. c Ve hemen arkasndan (daha JSP bu listeyi grmeden) Hibernate transaction o commit edilir ve session kapatlr. Bunun yaplma sebebi, elimizdeki son Java kodlama noktasnn Action execute metotunun son satr olmasdr! JSP iine c Java komutlar koyamayz, unk View ve Controller kavramlarn birbirine c u kartrmamak gerekir. s En sonunda ilem sras JSPye geldiinde ve sayfann listeye bakmas gerektiinde, s g g elinde daha ierikleri somutlanmam bir Car listesi olacaktr. Bu listenin ieriin c s c g erimeye altnz anda, Hibernate LazyInitializationException hatasn s c s g verir [1, sf. 300], unk Hibernate elindeki Car nesnelerinin ieriini doldurmaya c u c g uramaktadr, ama elinde bunu yapacak Hibernate session yoktur. g s 56

GELISTIRME ORTAMI Bu hatadan kurtulmak iin, evet, baz Hibernate ayarlaryla oynamak suretiyle c bir anda ykleme (fetching) seviyesini arttrabilir, ve Car listesi alndnda Car u g nesnelerinin yklenmesini zorlayabiliriz. Ya da, listeyi alnca Action iinden u c elle/zorla bu listeyi gezerek Carlarn yklenmesini zorlayabiliriz. Fakat bu iki u seimden birincisi Web dnyasnn bir gerekliliini eleme dosyalar uzerine c u g s yanstarak ileride yapabileceiniz performans ayarlarlama (tuning) manevra g alannz kstlar. Ikinci seenek ise, elle yazlm, fazla ve gereksiz bir koddur c s (Kural #7 ihlli). a Tavsiyemiz Webe zel bir problemin Webe zel ve tek bir yerde zlmeo o co u sidir. Servlet ltreleri burada yardmmza yetiiyor. Altta gsterilen ltre His o bernate transaction commit etme ve session kapatma iini JSP gsterimi s o bittikten sonra yapar. Servlet ileyi kurallarna gre, chain.doFilter ars s s o c g geri geldikten sonra, JSP grntlenmesi bitmi demektir. Bu nokta da Hiberou u s nate kapan ilemlerini yapmak iin en uygun yerdir. s s c Liste 3.2: HibernateCloseSessionFilter.java
public class HibernateCloseSessionFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { chain.doFilter(request, response); HibernateSession.commitTransaction(); } finally { HibernateSession.closeSession(); } } public void destroy() { } }

Liste 3.3: web.xml


<web-app> ... <filter> <filter-name>HibernateCloseSessionFilter</filter-name> <filter-class> org.mycompany.kitapdemo.util.HibernateCloseSessionFilter </filter-class> </filter> <filter-mapping>

57

3. Web Uygulamalar
<filter-name>HibernateCloseSessionFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> ... </web-app>

Bu ayarlardan sonra, artk Struts Action kodlarnda commit ve close ilemlerini s yapmamza gerek kalmaz. Hibernate kapan ilemleri ka tane Struts Action s s c ilemi olursa olsun JSP sayfasnn grntlenmesi bittiinde hemen devreye s s ou u g sokulacaktr.

3.3.5

Hzl Gelitirme s

Kitap rneklerimizin hepsi gelitirme ortamnda Ant programn kullanmako s tadr (Ant hakknda ek detaylar A.3 blmnde bulabilirsiniz). Ant, aynen ou u make gibi, bir komut dosyas kullanr; build.xml dosyasnda derleme (compilation), test, deployment gibi gelitirme srecinde lazm olacak tm ilemler s u u s yazlm hlde bulunur. Demomuz iin hazrlanan Ant build.xml dosyalar s a c birok projeden ders alnarak hazrlanmtr (bkz A.1 blm). Pek ok proc s ou u c jede gereken hzl gelitirme destei, yni sadece deien dosyalarn derlenmesi s g a gs ve deploy edilmesi build.xmldeki compile ve dist hedeeriyle salanmtr. g s Sadece deien kodlarn derlenmesi olduka ak olduu iin bu konu detayna gs c c g c girmeyeceiz. Hzl deployment destei yledir: Eer gelitirme srasnda sadece g g so g s JSP kodu deitirdiyseniz, gs
> ant dist

komutunu kullanarak sadece deien JSP dosyalarn hedef JBoss dizinine gnderegs o bilirsiniz. JBoss, deien JSP dosyalarn annda ileme koyabilecei iin yeni gs s g c JSP dosyalarn test etmek iin Uygulama Servisini kapatp/amanza gerek c c kalmaz. Ne yazk ki ayn teknii norml Java kodlar (class dosyalar) iin kulg a c lanamyoruz (ki bu durum piyasadaki tm Uygulama Servisleri iin geerlidir). u c c Java ClassLoader kullanm ile alakal bir durum yznden, yeni derlenmi Java u u s class kodlarn JBoss alrken sonu dizinine gndermek, Uygulama Servisinin c s c o yeni kodlar ileme koymasn salamaz. Yeni kodlarn grlmesi iin, deploys g ou c ment sonrasnda Uygulama Servisini kapatp/amanz gerekmektedir. c

3.4

T rke Karakter Destei u c g

Daha ileri gitmeden Web Uygulamarnda Trke Karakter Sorunu balkl u c s sorunu ilememiz ve zmemiz gerekiyor. Her seviyeye ve katman ilgilendis co ren bu sorunu zer zmez, i mant odakl Struts tekniklerine devam edeco co s g bileceiz. g o Ilk nce terminoloji: Literatrde internationalization gibi ok uzun bir keu c lime yerine genelde i18n ibaresi kullanlr, unk internationalization kelimesinin c u 58

TURKCE KARAKTER DESTEGI ilk i ve son n har arasndan 18 tane harf vardr; Ksaca bu kelimeye i18n denmitir. Biz de yaznn geri kalannda i18n kelimesini kullanacaz. s g i18n, uygulamanzn her seviyesinde ayr bir ekilde zmeniz gereken bir s co sorundur. Daha basit olan StrutsHibSimple uygulamasndan daha zor olan StrutsHibTag uygulamasna ter ederken, zel olarak Trke karakter desteinin o u c g genel olarak i18n probleminin hangi noktalara etki ettiini teker teker greceiz. g o g Tm zm birarada StrutsHibTag rneinin kodlarnda bulabilirsiniz. u co u u o g

3.4.1

Apache

HTML belgelerinin sylediinin aksine, HTML sayfalarmzn banda o g s


<META http-equiv="Content-Type" content="text/html; charset=utf-8"/>

tanm kullanmak, utf-8 karakteri kodlamas kullanmak iin yeterli olmamakc tadr. Apachenin her HTML sayfasn utf-8 ile kodlamas iin, httpd.conf c dosyasndaki <VirtualHost> etiketi iine c
AddDefaultCharset utf-8

satrn eklemeniz gerekmektedir.

3.4.2

Http Request

Bir Web uygulamasnn Trke karakterleri ile alabilmesi iin Java seviyesinde u c c s c request nesnesi ve JSP sayfalar uzerinde karakter kodlamasn (character encoding) deitirmemiz gerekiyor. Bu iki kodlamay UTF-8 bazl yapmamz gs gerekmektedir. Request uzerinde yaplmas gereken deiiklii her Struts Action class gs g iinden yapabilirdik, fakat bu ayn kodun ok fazla tekrar etmesi demek olac c caktr, ve bu Kural #7nn ihlli olurdu. Tekrarn her trlsn ortadan kaldrmak a u uu u istediimiz iin, tm request bazl karakter kodlamasn tek bir Servlet lg c u tresi ile yapabiliriz. Bu ltre RequestCharacterEncodingFilter adl ltredir (StrutsHibSimple kodlar iinde bulunabilir). Filtreyi ileme koymak iin web c s c .xmlde alttaki gibi bir deiiklik yeterli olacaktr. gs
<web-app> <display-name>KitapDemo</display-name> <filter> <filter-name>RequestCharacterEncodingFilter</filter-name> <filter-class> org.mycompany.kitapdemo.util.RequestCharacterEncodingFilter </filter-class> <init-param> <param-name>requestCharacterEncoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter>

59

3. Web Uygulamalar

<filter-mapping> <filter-name>RequestCharacterEncodingFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> .... </web-app>

Java Servlet standartna gre bir ltre class sistemimizdeki herhangi bir o Servlet (ve bilahere Struts Action) class iletilmeden bile nce ileme konur. s o s Bu an, istediimiz karakter kodlamas deiikliini yapmak iin harika bir andr. g gs g c Daha Servlet bile request nesnesine bakmadan karakter kodlama deiikliini gs g tek bir yerden yapabilmi oluruz. Bir Servlet ltresi her request uzerinde s iletilir, bu sebeple kodlama deiiklii her Servlet ve her Action iin otomatik s gs g c olarak yaplm olacaktr. Bylece her Action uzerinde srekli tekrar eden bass o u makalp kodlar yazmaktan kurtulduk (Kural #7).

Sekil 3.2: Servlet Filtresi

Liste 3.4: RequestCharacterEncodingFilter.java


import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import import import import import import import javax.servlet.Filter; javax.servlet.FilterChain; javax.servlet.FilterConfig; javax.servlet.ServletException; javax.servlet.ServletRequest; javax.servlet.ServletResponse; java.io.IOException;

public class RequestCharacterEncodingFilter implements Filter {

60

TURKCE KARAKTER DESTEGI

public static final String REQUEST_CHARACTER_ENCODING = "requestCharacterEncoding"; private String encoding = null; public void init(FilterConfig filterConfig) throws ServletException { encoding = filterConfig.getInitParameter(REQUEST_CHARACTER_ENCODING); } private String getInitParameter(FilterConfig filterConfig, String parameterName) throws ServletException { String value = filterConfig.getInitParameter(parameterName); if (StringUtils.isEmpty(value)) { throw new ServletException(getClass().getName() + ": " + parameterName + " is required"); } return value; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(encoding); chain.doFilter(request, response); } public void destroy() { } }

Filtre iin gereken kodlama parametresi web.xml iinden (UTF-8 deeri) c c g init-param kullanlarak geilmitir. Deerin kod iinden alnmasn ltre c s g c iindeki getInitParameter metotu hallediyor. Parametrenin ismini aldktan c sonra
filterConfig.getInitParameter(requestCharacterEncoding)!

arsn yaparak, gereken parametre deeri okunup, request.setCharacterEnc g g coding ile ileme konmaktadr. s 61

3. Web Uygulamalar

3.4.3

JSP

JSP sayfasnn Trke karakterleri gsterebilmesi iin sayfa kodlamasnn (page u c o c encoding) deimesi gerekmektedir. Bu deiim, her sayfada yaplmaldr. O gs gs zaman her sayfann bana UTF-8 kodlamasn kullanmak istediimizi belirten s g bir ibare koymamz gerekiyor1 . Bu da yle yaplr: so
<META http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

3.4.4

Struts Resources

Struts uygulamalarnda JSP sayfasnda dinamik olmayan sabit alan tanm deerleri (input labels) (mesel isim, soyad gibi tarif deerleri) direk JSP g a g iine gmlebilir. Fakat, deiik dilde mteriye servis etmemiz gerektii zac o u gs us g man bu tanm deerlerinin de dinamik bir ekilde (dilden dile) deiebilmesini g s gs isteriz. O zaman, tanm deerlerinin her dil iin deiik bir dosyadan gelmesini g c gs salamamz gerekiyor. g Struts bu trden bir deiimi uygulama seviyesindeki ayar dosyasnn seimini u gs c dile bal olarak yapabilmekle destekler. StrutsHibSimple rneinde sonu g o g c dizini WEB-INF\classes altnda application.resources adl dosyada, uygulamamz iin gerekli hata mesajlarn koymutuk. Aslnda bu dosya iine istediimiz c s c g her tanm koyabileceimiz bir yerdir. Gerekli tanm, normlde JSP iine gmlen g a c o u alan tanm deerleri olabilir. Bu yaplnca bu dosya iindeki tanmlara JSP g c iinden bean:message Struts etiketi ile eriebiliriz. Daha nce c s o
<tr> <td> License Plate </td> <td> <html:text property="licensePlate" size="32" /> </td> </tr> <tr>

gibi gmlm deer kullanmak yerine, artk o u us g


<tr> <td> <bean:message key="main.license.plate"/> </td> <td> <html:text property="licensePlate" size="32" /> </td>
1 Bulut

F. Ersava, http://www.teknoturk.org/docking/yazilar/tt000144-yazi.htm. s

62

TURKCE KARAKTER DESTEGI


</tr> <tr>

kullanabiliriz. JSP kodu, bu sayede, hem Ingilizce hem Trke iin ayn kalr. u c c Bu yapldktan sonra,tanmlarn deiik bir dilde (mesel Trkede) deiik gs a u c gs kmas iin classes dizini altna application_tr.properties adnda yeni c c bir dosya koyarz. Bu dosyada, application.propertiesdeki her label iin c yeni dildeki karlklar konacaktr. s Artk taraycmzn dil seimini deitirdiimiz anda, mesel en Englishden c gs g a tr Trkeye getiimiz zaman, Struts otomatik bir ekilde application. u c c g s properties yerine application_tr.properties dosyasn semesi gerektiini c g bilecektir. Ornek olarak main.license.plate tanmn alalm. Ingilizce ve Trke iin u c c iki ayr dosya oyle gzkecektir. s o u Liste 3.5: application.properties
main.license.plate=License Plate

Liste 3.6: application tr.properties


main.license.plate=Plaka

Taraycnzda gerekli deiiklii yapp, taraycy ap kapattnzda ve JSPyi gs g c g tekrar yklediinizde, Ingilizce yerine Trke mesajlarn ktn greceksiniz. u g u c c g o c Resources Dosyas Iinde T rke Karakterler u c Resources dosyas hakknda almas gereken bir daha handikap vardr. applis cation_tr.properties dosyas iinde ne yazk ki uic harerinden sadece c g so u, , ve harerini direk kullanabiliyoruz. Dier Trke karakterler Struts c o g u c tarafndan ekrana yanl baslmaktadr. Bu harerin yerine 3.1 tablosundaki s kod deerlerini kullanmak zorundayz. g Tablo 3.1: Kodlar S s u g o U O I c C \u015E \u015f \u00FC \u011f \u00F6 \u00DC \u00D6 \u0131 \u0130 \u00e7 \u00c7 63

3. Web Uygulamalar Bu kod deeri dnumlerini komut satrndan native2ascii programn g o us kullanarak otomatik olarak yaptrabiliriz. JDKnizin bin dizini altnda olan bu program (javac ile ayn dizin) eer iinde trke karakterler olan bir reg c u c sources dosyas uzerinde iletilirse 3.1 tablosundaki dnumleri yapp ekrana s o us basacaktr. Bu sonular herhangi bir yeni dosyaya ynlendirmeniz (pipe) koc o mut satrndan ok basittir. Ornek olarak application_tr.properties iindeki c c trke karakterleri dntrmek istersek: u c o us u
native2ascii application_tr.properties > application_tr_new.properties

Yeni kodlarn olduu dosya, application_tr_new.properties dosyasdr. g

3.4.5

Hibernate

Hibernatein UTF-8 bazl karakter kodlamas ile alabilmesi iin UTF-8 kodc s c lamasnn Hibernate balants uzerinde set edilmesi gerekmektedir. Bu tanm g yapldktan sonra Hibernate bu deeri aynen alp JDBC veri taban balants g g uzerinde set edecektir. Hibernate iin gereken ekler 2.1 kod listesinde gsterilen tanmlara ek olarak c o hibernate.connection ayar ieren alttaki iki satrn eklenmesi demektir2 . c
<hibernate-configuration> <session-factory name="foo"> ... <property name="hibernate.connection.useUnicode"> true </property> <property name="hibernate.connection.characterEncoding"> UTF-8 </property> ... </session-factory> </hibernate-configuration>

3.4.6

Veri Taban

MySQL Versiyon 4.0dan itibaren, MySQLde Trke karakter depolamak iin yaplmas u c c gereken zel hibir ey yoktur. Paketi olduu gibi kurabilir, balatabilir, ve eer o c s g s g tarierimizin geri kalann takip ettiyseniz hemen kullanmaya balayabilirsiniz. s Oracle Testlerimizi yaptmz Oracle 10g uzerinde, Oracle kurulu aamasnn kendi g s s olaan deerlerini kullanarak yaratt veri tabannda Trke karakter probg g g u c
2 http://www.hibernate.org/74.html.

64

ETIKETLER lemi meydana gelecektir. Oracleda Trke karakter destei iin, veri tabann u c g c yaratrken character set iin AL32UTF8 ve national character set iin AL c c 16UTF16 kullanmanz gerekiyor. Bunlar yapldktan sonra, hem OCI hem de Thin JDBC srclerini kullanarak Oracle ile Trke karakter alverii yapauu u u c s s bilirsiniz. Oracle kuruluunda seilmesi gereken karakter setini gsteren ekran s c o grntsn ve dier kurulu ile ilgili detaylar 9.5.1 blmnde bulabilirsiniz. ou uu u g s ou u

PostgreSQL PostgreSQL ile Trke karakter kullanmak iin hem ilk kurulu ve veri taban u c c s yaratma aamasnda UNICODE karakter seti kullanlmas PostgreSQL servisinde s belirtilmelidir. Bu komutlar srasyla
> initdb -E UNICODE .. > createdb test

Dier kurulu detaylar iin 9.5.2 blmne baknz. g s c ou u

3.5

Etiketler

Sekil 3.3: Ornek Sayfa

65

3. Web Uygulamalar

3.5.1

Form Alkal Etiketler a

Struts/JSTL uygulamamzda grsel dnya ile alveri elimizdeki grsel veriyi o u s s o ilemek, ve ekrana basmak iin birok etiket trnn kullanldn greceksiniz. s c c uu u g o Etiketleri ana amalar balamnda iki byk guruba ayrabiliriz: Form, yni c g u u a kullancdan bilgi almaya yarayan etiketler, ve pr prezentasyon amal etiketler. u c Form ile bilgi alveriinde Strutsn kendi etiketlerini kullanacamz sylemitik. s s g o s Pr prezentasyon iin, birka Struts etiketi dnda arlkla JSTL etiketlerini u c c s g kullanacaz. g Checkbox JSP sayfasnda checkbox (seim kutusu) kullanm iin DynaActionForm uzerinde c c java.lang.Boolean tipli bir e tanmlamamz gerekiyor. og
<form-beans> <form-bean name="AddCarForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="available" type="java.lang.Boolean" initial=""/> ... </form-beans>

Bu eyi Forma balamak iin, JSP iinde html:checkbox etiketi kullanlmal. og g c c


<td> <html:checkbox property="available"/> </td>

D z Metin Girii u s Bu tr giri iin Form uzerinde String alan tanmlamak yeterlidir. u s c
<form-beans> <form-bean name="AddCarForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="licensePlate" type="java.lang.String" initial=""/> ... </form-bean> </form-beans>

JSP iinde ise, html:text kullanlr. c


<td> <html:text property="licensePlate" size="32" /> </td>

66

ETIKETLER Coklu Checkbox Birden fazla checkbox gurup hlinde ileyebilmek iin Struts multibox yaklamn a s c s kullanabiliriz. Bu yaklamda her seim iin ayr checkbox yaratmak yerine, s c c Form nesnesi uzerinde tek tanmladmz String[] dizisi iine, her seilen g c c checkbox iin daha nceden bizim tanmladmz bir kimlik deeri Action nesc o g g nemize gelecektir. Bu yaklam oklu checkbox ilemesini byk lude rahats c s u u o c latmaktadr. Kullanm iin Form uzerinde String[] tanmn yapmalyz. c
<form-beans> <form-bean name="AddCarForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="selectedItems" type="java.lang.String[]" initial=""/> ... </form-bean> </form-beans>

JSP iinde her seilen checkbox tekilerden ayracak bir kimlik tanm <html c c o :multibox>...</html:multibox> iinde baslmaldr. Orneimizde bu kimlik, c g Car nesnesi iin tekil olan licensePlate esidir. c og
<td> <html:multibox property="selectedItems"> <c:out value="\${car.licensePlate}"/> </html:multibox> </td>

Kullanc seimi yaptktan ve Formu Struts Actiona gnderdiinde (yni gnder c o g a o dmesine basldnda), Action seilmi olan checkboxlar u ekilde ileyecektir. ug g c s s s s
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { DynaActionForm daf = (DynaActionForm) form; String selectedItems[] = (String[])daf.get("selectedItems"); for (int i=0;i<selectedItems.length;i++) { ... // selectedItems[i], seilmi bir checkboxdan gelen c s // kimlik deerini tar g s ... } }

67

3. Web Uygulamalar Giri Olarak Liste s Liste (dropdown box) iin Form uzerinde bu listeden seilecek deerin tipi c c g belirlenmelidir. Bu genelikle java.lang.String olacaktr.
<form-beans> <form-bean name="AddCarForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="size" type="java.lang.String" initial=""/> ... </form-bean> </form-beans>

Orneimizde daha nceden belli uc araba lus (size) iin u kod tanmlamz: g o o c u c c s Kcuk iin s (small), orta iin m (medium) ve byk iin l (large). Bu kodlar u c c u u c JSP sayfasnda kullanc tarafndan okunabilir bir tarif ile ilintilendirmemiz gerekiyor. Bunu da html:select ve html:option ile yapacaz. g
<td> <html:select property="size" size="1"> <html:option value=""/> <html:option value="s" key="car.size.small" /> <html:option value="m" key="car.size.medium" /> <html:option value="l" key="car.size.large" /> </html:select> </td>

Grdumz gibi kodu html:option etiketinin value tabiri tanmlyoruz. Fakat o ug u key de ne? Bu deer, yni key=.. iinde olacak deer, application g a c g .properties dosyanzdan alnacak deerin anahtardr. Bu deer, seim lisg g c tesinin kullancya dnk olan taraf olduu iin html:optionn application o u g c .propertiesden gelmesi gerekiyor (ya da application_tr.properties). Liste 3.7: application.properties
car.size.small=Small car.size.medium=Medium car.size.large=Large

Liste 3.8: application tr.properties


car.size.small=Kk ucu car.size.medium=Orta car.size.large=Byk u u

68

ETIKETLER

3.5.2

s Prezentasyon ve Ilem Amal Etiketler c

Resim Gstermek o Resim gstermek iin html:img Struts etiketini kullanabilirsiniz. Resmin boyuto c larn ayarlamak iin width adl deiken kullanlir. Width, sadece genilik c gs s ayarn yapsa da boy lus genilie gre deiecei iin tek parametre yeterli o c u s g o gs g c olmutur. s
<html:img page="/pages/images/green.jpg" width="10"/>

URL Hazrlamak Dinamik olarak URL uretmek iin JSTL c:url etiketini kullanmamz gerekiyor. c c:url birden fazla parametreyi ekleme yeteneine sahiptir. Kullanm: g
<td> <a href="<c:url value="/struts-action-vesaire.do"> <c:param name="param1" value="\${object.value1}"/> <c:param name="param2" value="\${object.value2}"/> ... </c:url>"> <c:out value="\${object.description}"/> </a> </td>

Bu url, uretildikten sonra, http://host/struts-action-vesaire.do?param 1=xxx&param2=yyy gibi bir deeri tayacaktr. Url uzerinde olan xxx ve yyy g s deerleri, object.value1 ve object.value2 hangi deerleri tayorsa, onlar g g s olacaktr. Deiken object, genelde bir c:forEach komutundan gelir. gs Liste Gezmek Veri tabanndan gelen sonular gstermesi gereken bir JSP sayfasna ou zac o c g man tek bir sonu yerine, iinde birok sonucun olduu bir liste gelir. Bu listeyi c c c g JSTL ktphanesinin bir etiketi olan c:forEach ile hi etiket dilinin dna uu c s kmadan gezebilir, ve grsel olarak kullancya sunabiliriz. c o Ornek olarak StrutsHibTags rneindeki GetCarsAction Actionn alalm. o g Bu Struts Action, Hibernate kullanarak (CarDAO.java uzerinden) veri tabanndan bir Car listesi alr. Bu liste, bir java.util.List uzerindedir. Bu liste, ay nen olduu ekilde JSP sayfasna verilebilir. Bunu yapmak iin listeyi Session g s c uzerinde koymak yeterlidir.
CarDAO dao = new CarDAO(); request.getSession().setAttribute("carList", dao.fetchCarList());

Bu kod paras Hibernateden gelen listeyi carList adl Session deikeni c gs uzerine koymutur. Bu yapldktan ve kontrol JSP sayfasna getikten sonra s c listeyi pr etiket kullanarak gsterebiliriz. u o 69

3. Web Uygulamalar
<c:forEach var="car" items="\${sessionScope.carList}"> <tr> <td> <c:out value="\${car.licensePlate}"/> </td> <td> <c:out value="\${car.description}"/> </td> </tr> </c:forEach>

Bir Struts Actionn request.getSession().setAttribute ile Session uzer ine koyduu bir deere JSTLin nasl eritiine dikkat ediniz: sessionScope g g s g adl JSTL komutu kullanlmtr. Bu sayede Session uzerine konan herhangi s bir deikene erimek mmkn olmaktadr. gs s u u Ustte grlen c:forEach komutuna gre, carList listesi gezilecek, ve listou o edeki her eleman iin car deikenine listede sras gelen eleman konulacaktr. c gs Bu eleman iin c:forEachin altnda olan tm dier etiket ilemleri gerekletirilir. c u g s c s Ustte bu ilemler <tr>, <td> ve c:out gibi etiket ilemleridir. JSTL c:out, car s s nesnesine eritiinde (car.description ile mesel) o anda listede sras gelmi s g a s olan Car nesnesine bakyor olacaktr. Basit Deerleri Basmak g Basit tipli bir Java deikenini akrana basmak iin c:out etiketini kullangs c abilirsiniz. Mesel elimizde car referans var ise, bu referanstan eriilebilen lia s censePlate deerini <c:out value="\${car.licensePlate}"/> ile basabilig riz. JSTL, \$ iareti ile String, Integer ya da Boolean bazl tm deerleri s u g dinamik olarak Stringe evirme yeteneine sahiptir. Bu yetenek dier JSTL c g g deer okuyucu ve karlatrc etiketler iin de geerlidir. Bu adan JSTL, Perl g s s c c c ve Ruby dilleri gibi dinamik bir dil kategorisine girer. Java dili gibi gcl tip u u kontrolleri yapmaz. Bir tipi gereken dier bir tipe annda evirir. g c Deer Karlatrmalar g s s Basit ekilde bir if karlatrmas iin JSTL <c:if> etiketi kullanlr. Mesel s s s c a StrutsHibTags rneindeki detail.jsp dosyamzda bu ekilde bir karlatrma o g s s s kullandk. Eer car.available true ise bir renk, deil ise dier bir renk resim g g g ekrana baslyor.
<td> <c:if test=\${car.available == "false"}> <html:img page="/pages/images/red.jpg" width="10"/> </c:if> <c:if test=\${car.available == "true"}> <html:img page="/pages/images/green.jpg" width="10"/>

70

ETIKETLER
</c:if> </td>

Daha nce bahsedilen dinamik tip evirebilme yeteneini burada da kullanldna o c g g dikkat ekmek isteriz. Boolean olduunu bildiimiz bir eyi direk true ya da c g g og false String deerleri ile karlatrabilmemizi bu yetenee borluyuz. g s s g c Kademeli Karslatrma s Java dilinde switch...case kullanmnn JSP iinde kullanabileceimiz karl c g s g JSTL dilinin <c:choose>...<c:when> kullanmdr. Mesela, bir Car nesnesinin uzerinde olan Boolean tipli deer availablen doru ya da yanl olma artna g g s s gre bir karlatrma yle yazlabilir. o s s so
<td> <c:choose> <c:when test=\${car.available == "false"}> <html:img page="/pages/images/red.jpg" width="10"/> </c:when> <c:when test=\${car.available == "true"}> <html:img page="/pages/images/green.jpg" width="10"/> </c:when> <c:otherwise> <html:img page="/pages/images/gray.jpg" width="10"/> </c:otherwise> </c:choose> </td>

Eer car.available false ise krmz bir jpeg gsterilecek, eer true ise yeil g o g s bir jpeg gsterilecektir. Eer bu artlardan hibiri doru deil ise c:otherwise o g s c g g artna deriz, bu durumda gri renkli bir resim ekrana baslacaktr (tabii bir s us Boolean enin deeri kesinlikle ya true ya da false olebilecei iin, otherog g g c wise artna dmek imkanszdr). s us Komutlar, Form Gndermek o Kullanc bir Form uzerinden giri yaptktan sonra girilen deerleri gndere s g o bilmesi iin Gnder (submit) gibi bir dmeye ihtiyac vardr. Bu dmeyi c o ug ug kodlamak iin deiik yntemler mevcuttur. c gs o Ilk (ve tavsiye etmediimiz) yntem JSP banda <html:form action= g o s /add-car.do> gibi bir Struts hede tanmlamak ve gnderme dmesini o ug <html:submit>Ekle</html:submit> gibi bir tanmdan ibaret brakmaktr. Bu yntem olduka basit olsa da, baz sorunlara sebebiyet verecektir. Birincisi, ayn o c form altnda olan ama deiik Struts hedeerine gnderme yapmas gereken gs o dmeler yanyana olunca kar. Eer bu dmeler sayfann ok deiik yerug c g ug c gs lerinde iseler, para para <html:form> ap sonra hemen kapatp yerine bir c c c 71

3. Web Uygulamalar tane daha amak (her deiik hedef iin) mmkn olabilir, fakat ou zaman c gs c u u c g HTML dizayn buna izin vermemektedir. Hep ie yarayacak tek bir yntem renmenin yararlar ortada olduu iin s o og g c tavsiyemiz, html:formun belirledii hede dikkate almayan, ve kendi hedeni g kendi belirleyen dmeler kullanmanzdr. Bunun iin html:submit yerine, ug c html:link ve JavaScriptin bir birleimi olan aadaki stili kullanacaz. s s g g
<html:link href= styleClass=action onclick=document.AddCarForm.action=add-car.do; document.AddCarForm.submit();return false;> Ekle </html:link>

Kendi kodlarza uyarlamak iin bu rnekte deitirmeniz gereken iki yer, Adc o gs dCarForm yerine kendi formunuz, ve add-car.do Struts hede yerine kendi hedenizdir. Bu komut JSP sayfasnda bir URL grnts basar. Eer URL grnts yerou uu g ou uu ine daha dmevari bir grnt istiyorsanz, html:img ile bir JPG dme ug ou u ug grnts yaratp onu kullanabilirsiniz. Fakat prensip olarak kullanlan teknik ou uu html:link rneine ok benzer. o g c
<td> <html:img page="/pages/images/add.jpg" styleClass="action" onclick="document.AddCarForm.action=add-car.do; document.AddCarForm.submit();return false;"/> </td>

Burada dgme grnts /pages/images/add.jpg adl dosyadan alnarak, u ou uu JSP sayfasna konmutur. Bu grnt tklandnda JavaScript uzerinden onclick s ou u g ile Struts add-car.do hede arlacaktr. c g Bu yaklamn tek dezavantaj dme uzerindeki metni artk String bazl s ug deil ama bir JPG resimden aldmz iin, dil deitirdiimizde (Ingilizce yerg g c gs g ine Trke gibi), grnt deitirmek iin baka bir JPG kullanmak zorunda u c o u u gs c s kalmamzdr. Bunun iin sayfa dilini JSP iinden alp <c:if> ile deiik diller c c gs iin hazrlanm JPG grntleri arasndan bir seim yapabilirsiniz. Fakat bu c s ou u c kullanm, i18n balamnda, String bazl kullanm kadar temiz olmayacaktr. g Tavsiyemiz html:linki kullanp URL grntsnn fontlar ve belki alt izgisi ou uu u c ile oynayarak, (mesel iptal ederek) dmeye benzer ekle getirmeniz, ve Strutsn a ug s mevcut i18n desteinden faydalanmanzdr. g c Sayfa Iine Sayfa Eklemek Eer baz JSP kodlama kalplar birok sayfa iinde tekrar ediyorsa, bu tekrar g c c eden kodlar tek bir JSP dosyas iine koymak, ve gereken yerde sadece bu tek c dosyay tek bir komutla dahil etmek kod idaresi asndan yararl bir davrantr. c s Bunun iin, JSP etiketi <%@ include file ..%> komutunu kullanabilirsiniz. c Kullanl ekli ok basit: ss c 72

Tiles
<%@ include file="/pages/common.inc"%>

Bu rnekte common.inc adl sayfa, ok tekrar eden kodlar ieren merkezi sayo c c fadr. Gereken yerden <%@include file> ile dahil edilmitir. Sonek .jsp yers ine .inc kullanlmasnn sebebi, tek bana alamayacak JSP kodlarn (.inc) s c s dier sayfa kodlarndan ayrmaktr. g

3.6

Tiles

Tiles (kiremit, fayans) kavram, btn sayfalarn ablonunu merkezi olarak uu s tanmladktan sonra, her sayfa iin boluklar doldurma suretiyle ekran yaratma c s tekniidir. Her para bir tile (kiremit) olarak grlebilir. g c ou Bilgi ilem dnyasndaki Web sayfalarn ounun belli bir ablonu takip s u c g s ettiini grmsnzdr. En karmak, grsel birok ey ieren alveri sitesinde g o us u u u s o c s c s s bile sayfalar arasndaki benzerlikten hangi boluklarn ne zaman dolduuna s g dikkat ederek bu ablonun niteliini takip edebilirsiniz. s g En basit ablon tr yledir: Ust bir reklam panosu, solda seim mens, s u u so c uu altta gn, ay, site kopya haklarn belirten bir ibare ve tam ortada ierik. u c

Sekil 3.4: Ornek Tiles Kullanm Bu yazmzda Struts Tiles teknolojisini kullanarak ablon, ve ablon kuls s lanarak sayfa yaratma tekniklerini greceiz. Bu blm iin yazlan kodlar o g ou c StrutsTiles dizini altnda bulabilirsiniz.

3.6.1

Kurmak

o Ilk nce struts-config.xml dosyasna u ifadeyi ekleyin. s


<plug-in className="org.apache.struts.tiles.TilesPlugin" > <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" /> <set-property property="definitions-parser-validate" value="true" /> <set-property property="moduleAware" value="true" /> </plug-in>

Simdi, (eer yoksa) struts-config.xml ile ayn dizin seviyesinde tiles-defs.xml g adl bir dosya yaratn. Sablonu kullanarak her sayfay teker teker tanmladmz g 73

3. Web Uygulamalar yer buras olacak. Dikkat edin, ablonu burada tanmlamyoruz. Sablon kullas narak sayfalar hayata geiriyoruz, ve onlara bir isim veriyoruz. Tiles-defs c .xml szdizimi detaylarn ileride vereceiz. o g

3.6.2

Sablon

Sablon iin sablon.jsp adnda bir JSP sayfas yaratalm. c


<META http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/WEB-INF/tags/struts-tiles.tld" prefix="tiles" %> <%@ taglib uri="/WEB-INF/tags/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/tags/struts-bean.tld" prefix="bean" %> <tiles:importAttribute name="menuSecim" scope="request"/> ... .... <body> <tiles:insert attribute="ustkisim"/> <table cellpadding="5" cellspacing="0"> <tr> <td> <table width="250"> <tr width="100%"> <td valign="top"> <br/> <tiles:insert attribute="menu"/> </td> </tr> </table> </td> <td valign="top"> <table> <tr> <td> <br/> <tiles:insert attribute="icerik"/> </td> </tr> </table> </td> </tr> </table> <tiles:insert attribute="altkisim" /> </body> </html>

74

Tiles s tiles:insert attribute ifadesine dikkat edelim. Ite bu ifade, ablon iinde s c bir boluk tanmlayan ifadedir. Sablon dosyas bir sayfann ana hatlarn s belirlemekte, fakat her sayfa iin deiik olacak yerlere bir isim vererek bo c gs s brakmaktadr. Ustteki rnekte menu, icerik, altkisim, ustkisim gibi bos yerler var. Buo raya tiles-defs.xml dosyas her sayfa iin gereken gerek JSP ieriini c c c g koyacak. Bunun da bir rneini grelim. o g o
<definition name="ornek@ekran" extends="dizim"> <put name="icerik" value="/sayfa123.jsp"/> <put name="menuSecim" value="kategori_1"/> </definition>

Bu rnek sayfay gstermek istiyorsak, struts-config.xml iinde bir Action o o c uzerinden taraycy bu sayfaya yneltmemiz lazm. Hemen yapalm: o
<action path="/ornek_Sayfa123Goster" type="com.sirket.filanca.GosterAction" name="OrnekForm"> <forward name="basari" path="ornek@ekran"/> <forward name="hata" path="/hata.jsp"/> </action>

Ornek@ekran ifadesi, sayfamza tiles-defs.xml iinde verdiimiz isimdir. c g s Taraycnn tand teki ismi de struts-config.xmlde tanmladktan. Iimizi g o bitti, artk taraycmzdan
http://localhost:8080/kitapdemo/ornek_Sayfa123Goster.do

yazdmz zaman, ekranmz grebileiz. g o g

3.6.3

Sablonda Olaan Deer Tanmlamak g g

Sablonumuzun birok tiles tanmladn grdk. Her sayfa iin bu bo yer c g o u c s lere her seferinde bir deer atamaktan kurtulmak iin, Tiles teknolojisi olaan g c g deerler tanma imkan vermitir. Sayfadan sayfaya fazla deimeyen ablon g s gs s deerlerini bir szde sayfa olarak tanmlayabiliriz. Sonra, teki gerek sayg o o c falar bu sayfadan kaltm suretiyle bu deerleri alrlar. g Altta bunun rneini gryoruz. Dizim ad verilen szde sayfa, fazla deimeyen o g ou o gs deerleri tanmlyor, ve kaltm yolu ile sayfa123 bu deerleri alyor. g g
... <definition name="dizim" path="/sablon.jsp"> <put name="icerik" value="/bos.jsp"/> <put name="menuSecim" value="baslangic"/> <put name="ustkisim" value="/ust123.jsp"/> <put name="menu" value="/menu123.jsp"/> <put name="icerik" value="/bos.jsp"/>

75

3. Web Uygulamalar
<put name="altkisim" value="/alt123.jsp"/> </definition> ... ... <definition name="ornek@ekran" extends="dizim"> <put name="icerik" value="/sayfa123.jsp"/> <put name="menuSecim" value="kategori_1"/> </definition>

JSP Sayfalara Parametre Gemek c Tiles teknolojisinin dier zellii her sayfaya JSP baznda okunabilen bir g o g parametreyi tiles-defs.xml tarafndan geilebilmesidir. Bunun faydalar, mesele, c dinamik bir men gsterirken ortaya kmaktadr: Bir mennn gsterdii kateu o c u u o g gori balantsna ya da bir sayfa bana tkladmzda menu.jsp tilenn hangi g g g kategoride olduunu bilmesi gereklidir. Cunk menu.jsp tek bir tiledr, ama g u farkli sayfalara gre farkl grntler vermesi gerekmektedir. o ou u Bunun zm sablon.jsp iinde en usste yaptmz co u u c g
<tiles:importAttribute name="menuSecim" scope="request"/>

ifadesidir. Bylece tiles-defsda her sayfa iin tanmlayabildiimiz o c g


<put name="menuSecim" value="kategori_1"/>

ifadesi yetecektir. Ustteki rnek menuSecim olarak kategori 1 deerini gnderiyor. o g o Bu deer menu.jsp tarafndan okunarak, logic:equal ile test edilerek dinamik g JSP gstermesi mmkn olacaktr. o u u

3.7

Hata Mesajlar Idaresi

Struts Actionlarn yazarken bu nesnelerin Hibernate veya dier alt tabaka g kalclk (persistence) programlarndan, ya da kullancnn veri girerken yapt g hatalar yakalamak iin en iyi yer olduunu unutmamamz gerekir. Programmzn c g Java istisnas (exception) olarak frlatabilecei hatalarnn Actionndan yukarya g kmasna izin vermememiz, bu hatalar yakalayp, kullancya daha anlaml c mesajlar aktarmamz gerekir. Tabii btn Action execute islevini koskoca bir uu try {} catch(Exception ..) ile evrelemek de fazla genelci olabilir; En iyc isi ilgilendiimiz Exceptionlar ilgilendiimiz tip seviyesinde yakalamamz ve g g onlara zel hatalar gstermemizdir. o o Kullancya gzel formatlanm ekilde gsterilecek hatalar gerektii zaman u ss o g u Struts kod kalbn kullanabilirsiniz. s
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {

76

Hata Mesajlar Idaresi


... ActionErrors errors=new ActionErrors(); try { // Hibernate ile ilemler, ilem mant vs.. s s g } catch (RecordNotFoundException e) { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionError("kayit.yok.hatasi")); saveErrors(request,errors); return mapping.findForward("fail"); }

Bunu yaptktan sonra ve kontrol, hata durumundan sonra JSP sayfasna geince, c hata u ibare ile ekrana baslabilecektir. s
<html:errors/>

application.properties kayit.yok.hatasi ad verilen cmle, application.properties dosyanzn u iinde tanmlanm bir hata mesajdr. Bu mesaj u ekilde gzkebilir. c s s s o u
kayit.yok.hatasi=Kay\\u0131t Bulunamad\\u0131

Hata mesajnde iinde Trke karakterler olduu iin, 3.4.4 blmnde rendiimiz c u c g c ou u og g uzere, esas karakter yerine onun ascii kodlamas kullanlmtr. s

3.7.1

Parametre Gerektiren Hata Mesajlar

Statik (deimeyen) hata mesajlar, her durumda yeterli olmayabilir. Mesela gs eer veri tabannda bir urn bulamamsak, hangi urnn bulunamadn kulg u s u u g lancya bildirmek isteyebiliriz. Bunun iin, uygulamamzn properties dosyasnda c Struts {0} kullanm iimize yarayacaktr. s
urun.yok=rn kodu {0} veri tabannda bulunamad. U u

Bu bo braklan yer iine, gerek urn deerini Struts Action iinden dolduras c c u g c bilirsiniz.
ActionErrors errors=new ActionErrors(); ... try { ... } catch (UrunBulunamadiException e) { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionError("urun.yok", form.getUrunKodu())); saveErrors(request,errors); return mapping.findForward("fail"); }

77

3. Web Uygulamalar Bu rnek, veri tabannda urn bulunamamas halinde UrunBulunamadiExcepo u tion atldn, ve ActionForm uzerinde getUrunKodu adl bir alann varln g g varsaymaktadr.

3.7.2

Actionlarda Muamele Grmeyen Hatalar o

Kodunuz iine catch koymanz gerektirmeyecek baz hatalar olabilir. Mesela c kullancnn oturum zaman tkenmitir (expire) ve bu durum srekli Nullu s u PointerExceptiona sebebiyet veriyordur. Bu Exceptionn nereden ne zaman gelecei belli olmad gibi, btn Actionlar srf bu nadir hata iin try {} g g uu c catchlere bomak yanl olur. Struts, kodlamadan ziyade ayarlar ile birok ii g s c s yapmanz salar. Hibir Actionn yakalamam olduu hatalar yakalamak iin g c s g c struts-config.xmlde genel bir tanm ile kullancy b t n bu yakalanmam u u s Exceptionlar iin belli bir sayfaya gnderebilirsiniz. c o
<struts-config> ... <global-exceptions> <exception key="global.error.message" type="java.lang.Exception" handler="org.mycompany.kitapdemo.util.ErrorHandler"/> </global-exceptions> ... </struts-config>

Bu tanma gre her Actionda muamele grmeyen Exceptionlar iin kullancy o o c ErrorHandler adl bir nesneye gnderiyoruz. Bu nesne bizim tanmladmz o g ve ExceptionHandler adl nesneyi uzatan bir nesnedir. Kodunu StrutsHibAdv altnda bulabilirsiniz.
public class ErrorHandler extends ExceptionHandler { private static Logger logger = Logger.getLogger("appLogger"); public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException { logger.error("Struts Error", ex); return mapping.findForward("error"); } }

78

WEB KODLAMA KALIPLARI Bu kod sadece yakalanan genel Exception Log4J ile loglayp, ve sonra error ad verilen bir ActionForward geriye dnmektedir. Siz kendi uygulamanz o iin, ActionForward dnmeden nce daha fazla kurtarc iler yapan kodlar c o o s yazabilirsiniz. ErrorHandlerdan ismi error adnda bir ActionForward dnleceine gre, o u g o bu forward belirleyen bir struts-config.xml tanm daha yapmamz gerekiyor. Bunu da global-forwards altnda yapabiliriz.
<global-forwards type="org.apache.struts.action.ActionForward"> <forward name="error" path="/pages/error.jsp"> </forward> </global-forwards>

Bu forwarda gre, error kodu error.jsp adl sayfaya ynlendirilecektir. Bu o o sayfa uzerinde genellikle kullancya sistem bakcsna bavurmas gerektii gibi s g genel mesajlar verilir. Bu tr hata muamelesinin btn Exceptionlar iin devreye gireceini biliyu uu c g oruz, unk Java nesnesel hiyerarisine gre, btn Exceptionlar java.lang c u s o uu .Exception adl nesneyi uzatmak durumundadr. <global-exceptions> altnda exception etiketini ayn struts-config .xml iinde birden fazla kullanabilirsiniz. Burada her zel Exception iin bir c o c yakalayc tanmlayabilirsiniz, Struts sistemi, elinde muamele grmemi bir Exo s ception olunca, zelden genele doru btn yakalayclar teker teker kontrol o g uu edecektir. Hi bir zel yakalayc yoksa, Exception iin olan en genel yakalayc c o c ileme konur (eer varsa). s g

3.8

Web Kodlama Kalplar

Struts temellerinin ve grsel birimlerin anlatlmas tamamlandna gre, rnek o g o o kurumsal uygulamamz olan bu pasta uzerinden dikey dilimler kesmeye balayabiliriz. s Pastann dilimlerinden her biri tm katmanlara bir kez dokunan ilevler/grevler u s o olacaklar. Her deiik dikey dilim ile deiik bir Kurumsal Web kodlama kalbn gs gs gstermeye uraacaz. o g s g

3.8.1

Tek Nesne Y kle ve Gster u o

Bu pasta diliminde detay istenen bir nesnenin seilmesi, yklenmesi, gsterc u o ilmesi grevini yerine getireceiz. Ykle ve gster ilevi genellikle bir JSP o g u o s URLinden nesne uzerine tklanmas ile balar. Yklemek ile grevli Struts s u o Action ile gereken yklenir ve JSP ile gereken bilgiler ekrana baslr. u Uzerine tklanan URLin main.jsp sayfasndaki listede hazrlanm olduunu s g farz ediyoruz. Bu balant URL parametresi olarak bir arabay tekil olarak kimg liklendirebilmemiz iin gereken licensePlate parametresinin tamaktadr. c s Eer main.do hedeni ykledikten sonra taraycnzda View | Page Source g u seeneini kullansanz, aadaki gibi HTML kodlarn greceksiniz. c g s g o 79

3. Web Uygulamalar
<table> ... <tr> ... <td> <a href="/kitapdemo/show-car-details.do?licensePlate=plate123"> plate1:tarif123 </a> </td> ... </tr> </table>

URLe bakarsanz, tarif olarak plate1:tarif123 metnini tayan URLe tklannca s /kitapdemo/show-car-details.do Struts Actionna licensePlate parametresi iin plate123 deerinin geileceini gryoruz. Struts Actionlarn nasl c g c g ou tanmlandn 3.2.3 blmnde grmtk. g ou u o us u Struts show-car-details.do hedenin muamale (handle) edilmesi iin bir c Action yazmamz gerekiyor. Bu Action tanm ve Java kodlar (StrutsHibTag projesi) yle gzkecektir. so o u Liste 3.9: struts-cong.xml
<struts-config> <action-mappings> <action path="/show-car-details" scope="session" type="org.mycompany.kitapdemo.actions.ShowCarDetailAction" validate="false"> <forward name="success" path="/pages/detail.jsp"/> <forward name="fail" path="/main.do"/> </action> ... </action-mappings> </struts-config>

Liste 3.10: ShowCarDetailAction.java


1 2 3 4 5 6 7 8 9

package org.mycompany.kitapdemo.actions; public class ShowCarDetailAction extends Action { private static Logger logger = Logger.getLogger("appLogger"); public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,

80

WEB KODLAMA KALIPLARI


10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

HttpServletResponse response) throws Exception { String licensePlate = request.getParameter("licensePlate");

Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); Car car = (Car)s.get(Car.class, licensePlate); request.getSession().setAttribute("car", car); return mapping.findForward("success"); } }

Satr satr aklama: c 13: Actiona gelen ve HttpServletRequest uzerinde olan licensePlate deikenine erimek iin, getParameter ars kullanlmtr. Bu ar, gs s c c g s c g pr servlet (Struts olmayan) ortamdan tandk gelebilecek bir ardr. u c g Deikenin deeri, yine ayn ismi tayan bir yerel deiken uzerinde sakgs g s gs lanr. 16-17: Hibernate Session alr ve yeni bir transaction balatlr. c s 19: Reguestden gelen parametre kullanlarak, Hibernate get ars ile c g licensePlatee sahip olan Car nesnesi yklenir. u 22: Baar kodu olan success geri dndrlr. Buna dayanarak, strust s o u uu -config.xmldeki ayar, ilem srasn detail.jsp adl sayfaya devam s ettirecektir. Kontrol, JSP sayfasna gelince c:out, c:when, c:if gibi etiketler kullanlarak eriilen \${car.licensePlate}, \${car.carSize} gibi deerler kullancya s g sunulabilir.

3.8.2

Nesne Ekle

Bu kodlarda bir Car nesnesinin sisteme eklenmesi rneini greceiz. Tm kodo g o g u lar StrutsHibAdv kodlar projesinde grebilirsiniz. Eklenmesi gereken Car o formunda, arabann plakas, tari gibi StrutsHibTags projesindeki elere og ek olarak, arabann elde olup olmad, lus gibi yeni eleri ekledik. Bu g o c u og eler JSP sayfasnda yeni Form html: etiketleri olarak ortaya kacaklar. og c Ayar dosyas struts-config.xml iinde ayn ekilde JSPdeki forma uygun c s bir Struts DynaActionForm nesnesi yaratmamz gerekiyor. 81

3. Web Uygulamalar Liste 3.11: Form Beanleri


<struts-config> <form-beans> <form-bean name="AddCarForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="licensePlate" type="java.lang.String" initial=""/> <form-property name="description" type="java.lang.String" initial=""/> <form-property name="available" type="java.lang.Boolean" initial=""/> <form-property name="size" type="java.lang.String" initial=""/> ... </form-bean> </form-beans> ... <action path="/add-car" scope="session" type="org.mycompany.kitapdemo.actions.AddCarAction" name="AddCarForm" validate="false"> <forward name="success" path="/main.do"/> <forward name="fail" path="/main.do"/> </action> </struts-config>

Liste 3.12: AddCarAction.java


1 2 3 4 5 6 7

package org.mycompany.kitapdemo.actions; ... public class AddCarAction extends Action { private static Logger logger = Logger.getLogger("appLogger"); public ActionForward execute(ActionMapping mapping,

82

WEB KODLAMA KALIPLARI


8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { DynaActionForm daf = (DynaActionForm) form; Car car = new Car (); BeanUtils.copyProperties(car, daf);

Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); s.save(car); // form icindeki degerleri sil HttpSession session = request.getSession(); session.removeAttribute(mapping.getAttribute()); return mapping.findForward("success"); } }

Satr satr aklama: c 13: Struts execute metotundan gelen ActionForm, DynaActionForm nesnesine evirilir (casting). c 16: Struts, JSP ile Form nesnesinin iindeki deerleri birbirine eitleyebildii c g s g iin, eldeki DynaActionForm, kullancnn doldurduu bilgilerle dolu gelmitir. c g s Bu bilgileri bo olarak yarattmz Car nesnesine tamak iin, BeanUs g s c tils yardmc nesnesindeki copyProperties komutunu kullandk. Bu ar, arka planda dinamik olarak metot kefedebilen ve arabilen Java c g s c g Reection teknolojisini kullanarak, iki nesne arasndaki isimleri ayn olan eleri birbirine set etme zelliine sahiptir. Struts ActionForm ve Hiog o g bernate POJO arasndaki veri tamalar iin vazgeilmez bir yardmc s c c aratr. c 18-27: Car nesnesini veri tabanna eklemek iin gereken Hibernate ilemleri. c s 24-25: ActionForm nesnesinin oturumdan (session) kartlmas. Bunun c yaplma sebebi, ekleme ilemi bittikten ve main.do hedene (bilahere s main.jsp sayfasna) tekrar gelindiinde, formda biraz nce girdiimiz g o g deerlerin tekrar gzkmemesini salamaktr. Bildiimiz gibi struts- g o u g g config.xmlde AddCarForm, session-sreli (scope) olarak tanmlanmt, u s bu yzden, eer sessiondan zellikle atlmazsa, session ortada olduu u g o g srece orada kalacak, ve bir nceki ekleme ileminin deerlerini srekli u o s g u gsterecektir. o 83

3. Web Uygulamalar

3.8.3

Tek Nesne Y kle ve Deitir u gs

3.8.1 blmnde bir nesneyi ShowCarDetailAction ile ykleyip, arkasndan ou u u Struts ile detail.jsp adl sayfaya gsterim iin gndermitik. Simdi, detail o c o s .jsp gsterimi yerine edit.jsp adl bir gncelleme sayfasna ynlendirme yao u o pacaz (yni Struts ayarlar biraz deiecek), ve bu sayfa uzerinden, kullanc g a gs gncelle dmesine tkladnda ilemesi gereken yeni bir gncelleme aku ug g s u siyonunu, UpdateCarAction kodlarn tanyacaz. Fakat ilk nce, gncelleme g o u gndeme gelince ok meydana kan bir sorundan bahsetmemiz gerekmektedir: u c c Cakan Gncelleme Sorunu. s u Cakan G ncellemeler s u Cok kullancl kurumsal uygulamalarda gncelleme sz telfuz edilince u o u a hemen akla gelen bir yan sorun ortaya kar; Cakan Gncelleme. Bu sorun c s u hasr altna atlabilecek bir sorun deildir, unk sistemin doru almas bu g c u g c s sorunun doru zlebilmesine baldr. g co u g Sorunu anlayabilmek iin yle bir senaryo hayal edin: Kullanc A ve B, ayn c so kayt #123e eriiyorlar. Ikisi de bu kayda nce ekrannda yle bir bakyor. s o so Daha sonra, ikisi de bu kayd kendine gre deitiriyor (diyelim ki bu deitirme o gs gs haklar sistemde tannm). Gncelleme aksiyonuna gelince, kullanclardan biri, s u gncelle dgmesine basyor, teki kullanc kahve molas iin kalkyor, ve ayn u u o c dmeye 20 saniye sonra basm oluyor. (Ya da, tamamen raslant sonucu bir ug s kullanc dgmeye tekinden 2 milisaniye nce basyor, sonu ayn olacaktr). u o o c Bu durumda, dmeye en son basan kullancnn deiiklikleri sisteme girmi, ug gs s bir ncekinin deiiklikleri yokolmu olacaktr. o gs s Burada diyebilirsiniz ki gzel, zaten en gncel veriyle almak doru deil u u c s g g midir?. Fakat duruma iyice bir bakmak gerekir: Tarif edilen trden bir sisu tem en son verinin ne olduunu tamamen raslantsal bir ekilde semitir, ve g s c s bu trden bir i sreci ou (hatta hibir) irket iin kabul edilir deildir. u s u c g c s c g Kullanc Ann deiiklikleri, ona hibir haber verilmeden yokedilmitir ve kulgs c s lanc Bnin de bu nemli deiikliklerden haberi olmamtr. Evet belki de, o gs s ayn deiikliklerin bazlarn Bde yapmtr, fakat Bnin yapmad ama gs s g Ann yapm olduu baz gncellemeler B iin lazmdr. s g u c Cakan gncelleme sorununu (kurumsal bir uygulama olmasa da) mesel s u a CVS gibi kaynak kod idare sistemleri iin de geerlidir. Ve dikkatinizi ekerim, c c c dosya bazl alsan bu sistemlerde bile, bir nceki deiiklik, kaybedilmez. c o gs Veri taban uygulamalarnda zm kitleme tekniini kullanmaktan geer. co u g c Modern mimarilerde bu kitlemeyi gerekletirmenin iki yolu vardr: Iyimser c s Kitleme ve Ktmser Kitleme. ou Kt mser Kitleme o u Ktmser kitleme bir kayda erien ilk kullancnn o kayd kitlemesi anlamna ou s gelir. Arkadan gelen dier kullanclar ayn kayda eritiklerinde (yni okumak g s a 84

WEB KODLAMA KALIPLARI iin bile) en iyi ihtimalde bekler, en kt ihtimalle bunu yapamayacaklarna c ou dair bir mesaj grrler. Eer o kayd deitirmek istiyorlarsa, ilk kullancnn o ou g gs kayt ile iinin bitmesine kadar beklemeleri gerekir. Ilk kullancnn ii bitince s s kilit zlr, ve dier kullanclar deien kayd en son hliyle grm olurlar. co u u g gs a o us Bu noktadan sonra eer hal ayn kayd deitirmek istiyorlarsa kendileri kayda g a gs girip kitlemi olurlar (tabii ki hal bunu sadece bir tanesi yapabilir) gncelleme s a u ilemlerine balarlar. Bu tr kitlemeye ktmser denmesinin sebebi, her an s s u ou bir bakasnn ayn kayda girecei beklentisiyle kilidin en batan alnmas, ve s g s teki kullanclarn darda tutulmasdr. o s Yukarda tarif edilen trden bir kilit Web mimarisinde request bittikten u sonra bile tutulmas gerekecei iin, kitlemenin tabloda ayr bir kolon, ya da g c merkezi bir kilit idarecisi tarafndan kontrol edilmesi gerekmektedir, unk veri c u tabanlarnn i kilit sistemleri bir veri taban balants ve o balantdaki transc g g action kavramna yakndan baldr, ve requestler aras taban balantsn g g hibir zaman bal tutmamamz gerektiini biliyoruz. Yoksa sistemi lekleme c g g oc srasnda problemler yaarz. s Bu tr bir kitlemenin i sreleri asndan kesin gerekli olduu yerler vardr. u s u c c g Fakat, kilit uzerinde bekleme merkezi bir kilit idarecisine gitme gibi basamak lar ierdii iin, yksek lekli kurumsal uygulamalarda tercih edilmeyen bir c g c u oc seenektir. Daha iyi leklenebilen ve kullanm asndan veri doruluunu bozc oc c g g mayan dier bir seenek, Iyimser Kitleme tekniidir. g c g Iyimser Kitleme Bu kitleme tekniinde bir kayda erien her iki kullancnn gncelle dmesine g s u ug basmasna izin verilir (kilit nceden alnmaz), fakat gncelleme ilemi veri tao u s banna ikinci erien kullanc bir hata mesaj grr. Bu mesaj, ona, kaydn s ou o yeni bilgileri girmekteyken deitiini syler, ve ikinci kullanc kaydn son gs g o hlini tekrar ykleyip, deiikliklerini tekrar yapmaldr. Baz nyz dizayna u gs o u larnda kaydn en son hli ile ikinci kullancnn deiiklikleri merge edilerek vera gs ilebilir, yni etrel bir se/been trnden birletirim ekran salanabilir. Ena c c g uu s g vai trden seeneklerin arasnda en basit olan bir hata mesajdr. Arka planda, u c yni veri taban ve uygulama servisi seviyesinde iyimser kitleme tekniinin a g gerekletirimi birka trl olabilir. c s c u u 1. Uygulama servisi seviyesinde bir kayt ekranda gsterilir gsterilmez hemen o o o deerler kullancnn oturumu (HttpSession) uzerine kopyalanr. Daha g sonra, kullanc gncelle dmesine bastnda o kaydn veri tabanndaki u ug g son hli SELECT ile bir daha alnr, ve oturum uzerindeki deerler ile if a g kullanlarak karlatrmalar yaplr. Eer uyumazlk var ise, hata verilir. s s g s 2. Gsterilen kaydn deerleri oturumda kopyalanr, fakat bu sefer gncelleme o g u srasnda veri tabanna gnderilen UPDATE komutuna bu deerler WHERE o g altnda ltre parametresi olarak verilir. Eer o deerler tabanda oktan g g c deimi ise UPDATE komutu baarsz olacaktr, unk ltre deerleri gs s s c u g 85

3. Web Uygulamalar hibir kayt bulamaz. UPDATEden geri gelen satr says (JDBC bunu konc trol edebiliyor) sfr ise hata mesaj verilebilir. 3. Veri tabanndaki her tabloda int tipinde bir versiyon kolonu bulunur, ve bu kolonunu deeri her satr iin sfrdan balar. Her UPDATE ileminde bu g c s s kolon bir arttrlr. Her okuma srasnda da bu versiyon tabii ki okunur, ve UPDATE sorgularna WHERE olarak eklenir. Bu yntemin ncekine gre o o o bir avantaj WHERE ltresinin gereksiz ekilde ok byyecek olmamasdr. s c u u Tek bir ekstra kolon ile i halledilir. s Hibernate altyaps 2 ve 3. seenekleri desteklemektedir. Hi fazladan kod c c yazmadan, zel Hibernate komutlarn kullanarak bu yntemleri kullanabiliriz. o o Bizim tavsiyemiz en basit ve etkili olan 3. yntemi kullanmanzdr. Eer mevcut o g bir ema ile alyor ve bu emada istediiniz kolonlara yeni bir versiyon kolonu s c s s g eklemenize izin verilmiyor ise 2. yntemi kullanabilirsiniz. Bu yntem iin [1, o o c sf. 174]e danabilirsiniz. Biz altta 3. yntemi tarif edeceiz. StrutsHibAdv s o g kodlar iinde versiyon bazl iyimser kitleme kullanan kodlar bulabilirsiniz. c Kopuk Nesneler ile G ncelleme u Kodun detayna inmeden nce son anlatmamz gereken konu kopuk (discono nected) bir Hibernate nesnesi ile gncelleme yapmaktr. Web uygulamalarnda u Car ya da Garage gibi nesneleri detay ekrannda gsterdikten sonra Hibernate o oturumunu kapatrz ve detay iin kullandmz nesne kopuk (disconnected) c g bir nesne haline gelir. Ayn ekilde Formdan gncellenmi bir veri aldmzda yeni bir Car ness u s g nesini new ile yaratrz, ve iini formdan gelen deerler ile doldururuz. Bu nesne c g de kopuk bir Hibernate nesnesi olarak kabul edilir. Tek problem, kopuk bir nesnenin direk alnarak saveOrUpdate arlmas c g durumunda ortaya kacaktr; Hibernate, o anda ayn oturum iinde ayn kimlii c c g tayan baka bir Car nesnesini oturumda tutuyorsa yeni bir Car nesnesi uzerinde s s gncelleme isteine NonUniqueObjectException hatasn verir. Bunu yapmasnn u g sebebi Hibernatein i ileyii ile alkaldr, her tekil nesneden oturum uzerinde c s s a bir tane tutmak, Hibernate mekanizmas asndan verilmi bir mimari karardr. c s Fakat Web mimarilerinde de dardan gelen kopuk nesne olduka kullanlan s c bir kodlama kalb olduu iin bu kullanma izin vermek iin, Hibernate prog c c gramclar bize merge adl yeni bir metot salamlardr. Eer kopuk bir nesneyi g s g alp direk gncelleme yapmak istiyorsanz, saveOrUpdate yerine merge fonksiyu onunu kullanmanz gerekiyor. Evet! Artk gncelleme kodlarnn kendisine ilerleyebiliriz. u Kodlar o Ilk nce yaplmas gereken, eski tablomuza bir versiyon kolonu eklemektir. 86

WEB KODLAMA KALIPLARI


DROP TABLE IF EXISTS car; CREATE TABLE car ( version int(10), license_plate varchar(30) default , description varchar(30) default , available int(1) default 0, car_size varchar(1) default ) ;

Car POJOsu uzerinde ayn ekilde yeni bir versiyon kolonu gerekiyor. s
public class Car { int version = -1; public int getVersion() { return version; } public void setVersion(int newVersion) { this.version = newVersion; } ... }

Eleme dosyas Car.hbm.xmlda, <version> adnda zel bir etiket kullanlmas s o gerekiyor. Bu etiket, Hibernatee, versiyon kontroll gncelleme yapmas iin u u c direktif verecektir.
<hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <class name="Car" table="car"> <id name="licensePlate" column="license_plate"> <generator class="assigned"/> </id> <version name="version" column="VERSION" unsaved-value="negative" /> <property name="description" column="description"/> <property name="available" column="available"/> <property name="size" column="car_size"/> </class> </hibernate-mapping>

Dikkat: version komutunun id etiketinden hemen sonra gelmesi mecburidir. Etiket unsaved-valuenun id etiketinde deil version etiketinde altnda g kullanlm olmasnn sebebi udur: Eer bir nesnenin kimlikleme yntemi ass s g o signed ise Hibernate bir POJOnun i verisine bakarak o POJOnun veri tac banna yazlp yazlmadn anlayamaz, unk kimlik POJOnun iinde hep g c u c 87

3. Web Uygulamalar olacaktr. Kimlik retiliyor olsayd, kimlik olmad zaman Hibernate bu u g nesnenin tabana daha yazlmadn anlard. g Peki bunu anlamak niin nemlidir? Cunk Hibernate saveOrUpdate ya c o u da merge, bir nesnenin yeni mi eski mi olduunu bir eylere bakarak anlayag s bilmelidir. Bu bilgiye dayanarak arka planda eski nesne iin UPDATE, yeni nesne c iin INSERT uretilecektir. c Versiyon kullanmnda nesnenin yenilii ya da eskilii version esine bakarak g g og anlalabilir. Versiyon deerleri sfrdan balad iin, yeni nesne iareti -1 olur. s g s g c s Hibernate yeni/eski olmann kriteri olarak <version> etiketi altnda negative tanmlamamza izin veriyor. O zaman her yeni POJO Car iin versionun c olaan deeri de -1 olmaldr ki bylece nesne hafzada ilk new ile yaratldnda g g o g version deeri -1 olur, ve Hibernate bu nesnenin veri tabannda mevcut olg madn hemen anlar. Eer bu nesne uzerinde saveOrUpdate ya da merge g g komutu kullanrsak, UPDATE deil, INSERT uretilecektir. g Son olarak versiyon bilgisini kullanc dunme zaman (think time) srasnda, us yni detay gsterme ve gncelleme ekranlar arasnda, tutacak bir yere ihtiyacmz a o u var: Bu yer, Form nesnesi olabilir. Nasl olsa Form uzerindeki her enin gster og o ilebilir trden olmas gerekmiyor. O zaman struts-config.xml yle deiecek. u so gs
<form-beans> <form-bean name="AddCarForm" type="org.apache.struts.action.DynaActionForm"> .... <form-property name="version" type="int" initial="-1"/> .... </form-bean> </form-beans>

Ilk deer (initial) olarak -1 deerini form uzerinden de vermi olmamzn g g s sebebi, AddCarAction durumunda yeni Car nesnesine bu deerin yazlmasn g zorlamaktr. Eer bunu yapmasaydk, ilk deer 0 olacak (Struts tarafndan verg g ilir) ve 0 deeri bu Car nesnesinin yeni bir nesne olduunu gstermeyecekti. g g o Son olarak, UpdateCarAction kodunu grelim. o Liste 3.13: UpdateCarAction.java
1 2 3 4 5 6 7

public class UpdateCarAction extends Action { private static Logger logger = Logger.getLogger("appLogger"); public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,

88

WEB KODLAMA KALIPLARI


8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

HttpServletResponse response) throws Exception { DynaActionForm daf = (DynaActionForm) form; ActionErrors errors=new ActionErrors(); String id = ""; String result = ""; try { Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); Car car = new Car(); id = car.getLicensePlate(); BeanUtils.copyProperties(car, daf); s.merge(car); result = "success"; } catch (org.hibernate.StaleObjectStateException e) { errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionError("optimistic.car.update.failed", id)); saveErrors(request,errors); HibernateSession.rollbackTransaction(); result = "fail"; }

// form icindeki degerleri sil HttpSession session = request.getSession(); session.removeAttribute(mapping.getAttribute()); return mapping.findForward(result); } }

Satr satr aklama: c 11: ActionForm nesnesi DynaFormAction nesnesine evirilir (cast). c 19-20: Hibernate Session ve yeni bir transaction balatlr. s 22: Gncellenmesi istenen nesne, bo olarak yaratlr. u s 24: BeanUtils metotlarndan copyProperties ile form uzerindeki deerler g otomatik olarak Car uzerine tanr. Versiyon deeri de bu tama srasnda s g s 89

3. Web Uygulamalar detay gsterme anndaki hli ile geri gelecektir, unk form uzerinde o a c u hatrlanan hali odur. 25: Hibernatein gncellemeyi balatmas iin merge arlr. Hibernate, u s c c g versiyon numarasna bakarak bu ilemin bir INSERT deil, UPDATE olduunu s g g anlayacaktr, ve ayrca version deerini WHERE ltresi iinde kullanarak g c gncelleme akmas sorununu zecektir. u c s co 27: Bu Action sonunda dnlecek durum kodu bu aamada success o u s olarak seiliyor, unk bu noktaya gelmisek exception atlmam demekc c u s s tir. 29-35: Eer gncelleme aksmas olursa, Hibernate bu durumu Staleg u c ObjectStateException hatas ile belirtecektir. Stale kelimesi Ingilizcede eskimi anlamna gelir, yni uzerinden gncelleme yaptmz nesnenin s a u g eskimi deerleri tad bize sylenmeye allmaktadr. Bu hatay s g s g o c s yakalaynca, ilk nce veri tabanndaki transaction geriye sarmamz/iptal o etmemiz (rollback) gerekir, ve, hatal durumdan kullancy haberdar etmemiz gerekir. Biz de application.properties uzerinde tanmlanm s optimistic.car.update.failed hatasn kullanarak bu durumu rapor edeceiz. Strutsta hata mesajlarnn tanmlanmas ve kullanlmas iin g c 3.7 blmne baknz. Veri tabanlar kavramlar iin 9 blmne danabilirsiniz. ou u c ou u s 35-41: Form deerleri oturum uzerinden kartlr. g c 42: Durum kodu geri dndrlr. o u uu

3.8.4

B y k Sonu Listelerini Sayfa Sayfa Gstermek u u c o

Kullanclar, eer uygulamadaki herhangi bir nesnenin listesini grmek isterg o ler ve bu liste tek sayfaya smayacak kadar byk olmas mmkn ise, prog u u u u gramclar listeyi blm blm gsterecek teknik stratejiler gelitirmelidir. Aslnda ou ou o s bu soruna teknik olmayan basit bir zm, mteriye ltreleme seenekleri co u us c salayarak sonu listesini kultlmekten geer. Mesel demomuzdaki Car nesg c uc u c a neleri, byk bir sistemde 10,000 saysna ulam ise, bu kadar arabay hibir u u s s c kullanc hibir listeleme ekliyle grmek istemeyecektir! Bu tr bir liste lc s o u treleme ile kultlmelidir. Ama ltre sonras bile elimizde ok sayda nesne uc u c varsa sayfalama tekniklerini kullanmak zorundayz. Hibernate, sayfalama iin Query nesnesi uzerinde set edilebilecek setFirstRec sult ve setMaxResults arlarn destekler. c g
Query query = .. query.setFirstResult(0); query.setMaxResults(20); List l = query.list();

90

WEB KODLAMA KALIPLARI Bu iki arya verilen int parametresi, srasyla, kanc satrdan itibaren, ka c g c c tane satr gsterileceini belirler. Istediimiz byk sonu listesinden daha fazla o g g u u c para grmek istersek, kanc satr parametresine yeni bir deer vererek ayn c o c g maxResults parametresi ile Queryden yeni bir List almalyz. Her yeni sayfa, veri taban uzerinde yeni bir SQL iletilmesi demek olacaktr. s Arka planda uretilecek SQL komutu her ticari veri taban urn iin farkldr. u u c Hibernate kullanmamzn faydasn burada hemen grmu oluyoruz, unk Hio s c u bernate, her taban iin lzm olan SQL komutunu bilir, ve SQL uretimini ona c a gre yapar. Bylece bizim ilem Java kodumuzun tabandan tabana deimesi o o s gs gerekmez. Tekniin Struts/JSTL ortamnda kullanlmasn grmek iin StrutsHibAdv g o c kodlarna bakabiliriz. Bu rnekte list.jsp sayfas, byk bir listeyi 0nc o u u ilk sayfadan balayarak ekrana basmaktadr. Veri tabanna ok miktarda veri s c yklemek iin sample_paging.sql dosyasndaki rnek verileri kullanabilirsiniz. u c o Kullanc komutunu karlayan Struts Action, ListCarPageAction iinde grlebilir. s c ou Page (Sayfa) Nesnesi Simdiye kadar takip ettiimiz kod kalplarnda actiona git, liste uret, say g faya dn zincirlemesini yapmstk. Bu uly sayfalama iin deitirmemiz o c u u c gs gerekecek. ListCarPageAction iinden List dnmek yerine yeni yazacamz c o g bir Page nesnesi dneceiz. Bunu yapmamzn sebebi, listeleme sayfalarnda o g oka kullanlan sonraki, nceki trnden dmelerin ne zaman aktif ne zac c o uu ug man pasif olacan bilebilmek iin soru soracamz bir nesnenin gerekliliidir. g c g g Eer sadece List dndrm olsaydk, bu sorular soramazdk, unk List, g o u us c u iinden geldii Query nesnesi ile tm alakasn o noktada kaybetmi olurdu. c g u s Yeni yazacamz Page class sonu listesi Listi iinde barndracak, ayrca g c c JSP sayfasnn hangi sayfa, daha kayt var m? gibi sorular sorabilmesini yardmc fonksiyonlar sayesinde salayacaktr. g Liste 3.14: Page.java
public class Page { private List results; private int pageSize; private int page; public Page(Query query, int page, int pageSize) { this.page = page; this.pageSize = pageSize; results = query.setFirstResult(page * pageSize) .setMaxResults(pageSize+1) .list(); }

91

3. Web Uygulamalar
public boolean isNextPage() { return results.size() > pageSize; } public boolean isPreviousPage() { return page > 0; } public List getList() { return isNextPage() ? results.subList(0, pageSize-1) : results; } public Integer getNextPageCount() { return new Integer(page + 1); } public Integer getPreviousPageCount() { return new Integer(page - 1); } }

Page classnn kullanm setFirstResult ve setMaxResultsdan bile rahat, unk Page nesnesine geilen parametre, kanc satr yerine kanc sayfa c u c c c deeri olacaktr. Sayfadan hareketle gerekli satr hesaplar arka planda Page g tarafndan yaplr. CarDAO kodlarndaki fetchCar sorgu metotu Pagei yle so kullanr.
public Page fetchCar(String currPage, String nextPage) { Session s = HibernateSession.openSession(); return new Page(s.createQuery("from Car"), new Integer(currPage).intValue(), new Integer(nextPage).intValue()); }

CarDAOyu kullanan Struts Action ise yle olacaktr. so


public class ListCarPageAction extends Action { private static Logger logger = Logger.getLogger("appLogger"); public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String currPage = request.getParameter("currPage");

92

WEB KODLAMA KALIPLARI


String maxPage = request.getParameter("maxPage"); CarDAO dao = new CarDAO(); request.getSession().setAttribute("page", dao.fetchCar(currPage, maxPage)); request.getSession().setAttribute("maxPage", maxPage); return mapping.findForward("success"); } }

Metot execute iinde ilk yaplan i hangi veri sayfasnn ve bu sayfada ka c s c tane satr grntlemek istenildiine dair (currPage ve maxPage) adndaki ou u g parametrelerin okunmasdr. Bundan sonra CarDAOyu yaratp bu parametreleri geerek fetchCar arsn yapabiliyoruz. Geriye geri gelen sonu Page nesc c g c nesini alp session uzerine yerletiriyoruz. Artk JSP sayfas session uzerinden s page referansn kullanarak sonu nesnemizi bulabilecektir. JSP sayfas yle c so olacaktr (ksaltlm kod olarak). s Liste 3.15: list.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

<table> <tr> <td> <c:if test=\${sessionScope.page.previousPage == "true"}> <a href="<c:url value="/car-list.do"> <c:param name="currPage" value="\${sessionScope.page.previousPageCount}"/> <c:param name="maxPage" value="\${sessionScope.maxPage}"/> </c:url>"> <bean:message key="main.previous.page"/> </a> </c:if> <c:if test=\${sessionScope.page.previousPage == "false"}> <bean:message key="main.previous.page"/> </c:if> </td> <!---- ayni eyi sonraki dmesi iin de yap ----> s ug c ... </tr> </table> <html:form action="/add-car.do"> <table> ... <c:forEach var="car" items="\${sessionScope.page.list}"> <tr>

93

3. Web Uygulamalar
27 28 29 30 31 32 33 34 35 36 37 38 39 40

... <td> <a href="<c:url value="/edit-car-details.do"> <c:param name="licensePlate" value="\${car.licensePlate}"/> </c:url>"> <c:out value="\${car.licensePlate}"/> : <c:out value="\${car.description}"/> </a> </td> </tr> </c:forEach> </table> </html:form>

Satr satr aklama: c 4-13: Onceki dmesinin gsterilmesi. Bu dmenin c:if koulu uzerinden ug o ug s gsterilmesini sebebi, sadece gsterilecek sayfa var ise uzerine tklanan o o nceki balantsna ihtiya olmasdr. c:if ile yaplan kontroln seso g c u sionScope uzerinden sessiona eritiini gryoruz. Ilgin bir kullanm s g ou c daha var: Sessiondaki page uzerinden geride sayfa olup olmad sorusu. g Bunu Page classnn isPreviousPage metotunu ararak yapyoruz. c g Zincirleme olarak ar yapabilmek JSTLin faydal bir zelliidir, sesc g o g sionScope.page.previousPage gibi. Bu ardan geriye gelen cevap bize c g daha fazla veri sayfas olup olmadn syleyecek. Bu satrlar arasnda, g o daha fazla sayfa olmas sorusuna true cevab gelmesi planlandmza g gre, o zaman, c:url ile nceki dmesini gsterebiliriz. Peki bu dme o o ug o ug hangi URL deerlerini tayacak? Eer biz currPage=3 uzerinde isek, g s g nceki URLi currPage=2yi gstermeli. Bu -1 ilemini yaptrmak iin o o s c Page classna getPreviousPageCount adl bir metot koymutuk. O kos mut ite burada ie yarayacak: s s
<a href="<c:url value="/car-list.do"> <c:param name="currPage" value="\${sessionScope.page.previousPageCount}"/>

ile URLimizi bir nceki sayfaya iaret edecek ekilde gsterebiliriz. Niye o s s o -1 gibi basit bir ilemi hemen sayfa uzerinde yapmadk? Cunk prensip s u olarak JSP uzerinde (<% %> ile) Java kullanmaktan kanmamz gerekiyor. c Bu tr kodlar, grsel mantk ile ilem mantn birbirine kartrrlar ve u o s g s bakm zor kodlara sebebiyet verirler. Eksiltme ve oaltma, tek bir yerde, c g ve bir Java classnn iindedir ve ait olduu yer de orasdr. c g 14-17: Buradaki c:if art, geriye gitme ilemi iin veri satr olmamas s s c durumunu kontrol eder. Eer Page nesnesi bize geride daha fazla satr g yok diyor ise, bu noktada nceki balants yerine, nceki kelimesini o g o 94

WEB KODLAMA KALIPLARI String olarak basarz, ama tklanabilir bir balant vermeyiz. Bylece kulg o lanc geriye gitme ilemini yapamayacaktr. s 18: Aa yukar ayn ilemleri bu sefer sonraki dmesi iin yaplr. s g s ug c Tekrardan kanmak iin bu kodlar gstermedik. Fakat, previousPage c c o yerine nextPage, ve previousPageCount yerine nextPageCount arlar c g kullanlr. Bu metotlarn tanmlar iin Page classna bakabilirsiniz. c 25-38: Onceki ve sonraki dmeleri sayfann ustnde yer alr. Hemen ug u altnda, listenin gsterimi yaplr. Artk tandk olan c:forEach ile \${ o sessionScope.page.list} deikenini geziyoruz. Page nesnesi uzerinde gs CarDAOdan gelen sonularn bir List olarak tutulduunu belirtmitik. c g s Listeyi gstermek iin eriimin yapld her burasdr. o c s g

3.8.5

Dosya Y klemek (File Upload) u

Uygulamamz iin, bazen, sadece kullanc tarafndan yklenebilecek bir dosyann c u sisteme alnmas gerekir. Bu dosya, bir JPEG resmi, bir PDF dosyas, ya da bir text dz metni olabilir. u Struts ile dosya yklemesi gerekletirmek iin, Commons FileUpload prou c s c jesini kullanmamz gerekiyor. Bu projenin jar ve bu jar kullanan rnek dosya o ykleme ilemi gerekletiren kodlar, StrutsUpload projesinde bulabilirsiniz. u s c s Projede gsterildii ekilde bir dosya ykleyebilmek iin, ncelikle, dosya o g s u c o ismini kullancya soran bir JSP sayfas yazmamz gerekiyor.
<html:form action="/upload.do" enctype="multipart/form-data"> Please enter the file you want to upload:<br/> <html:file property="formFile" /><br/><br/> <html:submit/> </html:form>

Etiket <html:form> iindeki <html:file> ile, sayfa uzerinde kullancya bir c dosya semesini salayan bir enin yerletirilmesini salyoruz. Formun gnderc g og s g o ilecei yer olarak ta /upload adl bir Struts Action tanmladk. Bu Action, g bizim yazdmz (ve her proje iinde olduu gibi kullanlabilecek) Uploadg c g Action kodudur. Ayar dosyas struts-config.xml iindeki tanm aadaki c s g gibidir:
<action path="/upload" type="org.mycompany.kitapdemo.actions.UploadAction" name="UploadForm"> <forward name="success" path="/pages/success.jsp"/> <forward name="error" path="/pages/error.jsp"/> </action>

Grdumz gibi Action, form olarak UploadForm alyor. Bu formun iinde o ug u c sisteme yklenmi olan dosya binary olarak tanmaktadr. Zaten bu sebeple u s s <html:form> iinde UploadActionn armnda enctype kullandk. Bunun c c g 95

3. Web Uygulamalar yaplma sebebi, UploadActiona verilen formun, uzerinde basit tipler olan bir form deil, btn bir dosya tayor olmasdr. g uu s Action, bu btn dosyay binary olarak alnca tek yapmas gereken belli uu bir dizinde bir dosya ap, dosyay o dizine yazmasdr. Dosya yazlmas bitip c geriye baar kodu dnlnce, nceden UploadAction iinde tanmlanm olan s o uu o c s dizin iinde yeni bir dosya olduu grlecektir. c g ou Eer bu yeni yklenen dosya uzerinde ek ilemler yaplmasn istiyorsak, g u s Strutsn modler zincirleme yapsn kullanarak yeni bir Action yazp Struts u ar zincirine dahil edebiliriz. Yni, mesel bir UploadedFileProcessorAcc g a a tion yazarak struts-config.xmlde tanmlarz
<action path="/process-upload" type="org.mycompany.kitapdemo.actions.UploadedFileProcessorAction" name="UploadForm"> <forward name="success" path="/pages/success.jsp"/> <forward name="error" path="/pages/error.jsp"/> </action>

ve nceki /upload zincirine u ekilde ekleriz o s s


<action path="/upload" type="org.mycompany.kitapdemo.actions.UploadAction" name="UploadForm"> <forward name="success" path="/process-upload.do"/> <forward name="error" path="/pages/error.jsp"/> </action>

Grldu gibi UploadAction baar (success) kodu artk JSP sayfas yerine, o u ug s yeni ileyici Actiona ynlendirilmitir. Nihai JSP sayfasna ynlendirmeye yas o s o pan, ileyici ilemleri bittikten sonra, UploadedFileProcessorAction class s s s olacaktr. Ileyici yeni Action kodu altta grlebilir. Kodun tek ihtiyac olan ou yeni yklenen dosyann yeri ve ismidir. Bu bilgileri kendisine gecilecek olan u UploadForm uzerinden hemen alnr.
public class UploadedFileProcessorAction extends Action { public UploadedFileProcessorAction() { } public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { UploadForm newForm = (UploadForm) form; String uploadedFile = newForm.getUploadedFileName(); // yeni yklenmi uploadedFile ile istediimiz ilemleri u s g s // burada yapabiliriz

96

WEB KODLAMA KALIPLARI


// .. return mapping.findForward("success"); } }

3.8.6

Kullanc Isim ve Sifre Kontrol (Login) u

Kurumsal uygulamalarda ok ihtiya duyulan kodlama kalplarndan biri sisc c teme giri kontrol iin kullanc ismi ve ifre istenmesi ve kullanc ismine s u c s dayanarak kullancya daha nce admin tarafndan verilen roller nda, kulo sg lancnn deiik ierik grmesini salamaktr. Mesel bir nans uygulamasnda gs c o g a banka hesaplarn sadece grebilen kullanclar olabilir, ve bu hesap bilgilerini o hem grebilen hem de deitirebilen kullanclar olabilir. o gs Login kodlama kalbn gerekletirmek iin, kullanc, ifre ve rol bilgisi c s c s idaresini Hibernate uzerinden yapacaz. Kullanc iin User, rol iin Role adl g c c iki POJO yaratlacak. Her Usern birden fazla Role altnda olabileceini ve g her Roleun birden fazla kullanc olabilecei gerekliliinden hareketle, bu iki g g nesne arasnda oka ok (2.5.3 blm) trnden bir nicelik ilikisi kuracaz. c c ou u u u s g Rol odakl dinamik ierik iin zel etiket (custom tag) teknolojisini kulc c o lanacaz. Aynen Struts html:, ya da JSTL c: etiketlerin gibi, biz de kendimize g zel bir etiket ktphanesi yaratabiliriz. Bu etiket ktphanesine mycompany: o uu uu etiketi uzerinden erieceiz. Etikette tanml inRole gibi bir soru ile, o anda s g sayfaya bakmakta olan kullancnn bir rol iinde olup olmad sorusunu sorac g bileceiz. g
<mycompany:inRole role="Admin"> Bunu sadece adminler grebilir o </mycompany:inRole>

Bu rnee gre kullanc Admin rolnde bir kullanc ise, bunu sadece admin o g o u grebilir mesajn grebilecektir. o o Bu kodun doru alabilmesi iin inRole etiketinin kullanc bilgisine erimesi g c s c s gerekir. O zaman, etiket ileme konmadan nce bir baka kodun kullanc s o s bilgisini daha nceden eriilebilir, merkezi bir yere yerletirmi olmas gereko s s s mektedir. Bu kod paras login.jsp adl bir sayfann gidecei LoginAction c g adl bir Struts Action olabilir. Bu kod iine gelen LoginFormdaki kullanc c ve ifre, veri tabannda (Hibernate ile) kontrol edilir, ve eer kullanc giriine s g s izin verilirse, sessiona o kullancya ait User konabilir. Bylece daha sonra o ileme konacak olan mycompany:inRole etiketleri, session uzerinden alacaklar s Userdan, Rolelarn vermesini isteyerek, sorulan rol altnda olup olmadklarn kontrol edebilirler. 97

3. Web Uygulamalar Tag Library Yaratmak Ustte tarif edilen tasarmn kodlanm hlini StrutsHibLogin projesinde bus a labilirsiniz. Bu kodu para para aklayalm. Bir etiket ktphanesi (tab lic c c uu brary) yaratmak iin, etiket Java kodu, etiket tanm dosyas (tld), ve web. c xmlde deiiklikler gerekir. Etiket kodu, alttaki gibi olacaktr. gs
public class InRoleTag extends TagSupport { String role; public String getRole() { return role; } public void setRole(String newRole) { this.role = newRole; } public int doStartTag() throws JspException { HttpServletRequest request = (HttpServletRequest)pageContext.getRequest(); HttpSession session = request.getSession(); User user = (User)session.getAttribute("user"); Set roles = user.getRoles(); boolean inRole = false; for (Iterator it = roles.iterator(); it.hasNext();) { Role role = (Role)it.next(); if (role.getRoleName().equals(this.role)) { inRole = true; } } if (inRole == true) { return EVAL_BODY_INCLUDE; } else { return SKIP_BODY; } } }

JSP sayfasnda etiket yklendii zaman arlan kod nce setRole daha sonra u g c g o doStartTag kodudur. Etiketin role=.. parametresini kullanmas Java kodu uzerinde setRole metotunun arlmasn tetikler. Tm parametreler set c g u edildikten sonra (bizim artlarmzda bir tane), sra doStartTag metotuna gelir. s 98

WEB KODLAMA KALIPLARI Bu metot iinde etiket altna den HTMLin gzkp gzkmeme kararn c us o u u o u vermemiz gerekiyor. Bunlardan birincisi iin EVAL_BODY_INCLUDE, dieri iin c g c SKIP_BODY sabit deerlerini dndrmemiz yeterlidir. g o u Bu karar verilirken session uzerinden User nesnesinin alndna dikkat edi g niz. O zaman nceden User oraya koyan (ifresini kontrol ettikten sonra) o s birileri olmal. Bu kod, yni LoginAction, yle olabilir. a so
public class LoginAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { HttpSession session = request.getSession(); Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); DynaActionForm daf = (DynaActionForm) form; if (logger.isDebugEnabled()) logger.debug("daf=" + daf); User user = (User)s.get(User.class, (String)daf.get("userName")); if (user.getPassword().equals((String)daf.get("password"))) { if (logger.isDebugEnabled()) logger.debug("user is authenticated"); session.setAttribute("user", user); } // form icindeki degerleri sil session.removeAttribute(mapping.getAttribute()); // geri don return mapping.findForward("success"); } }

Bu kodun grevi formdan kullanc ve ifreyi almak, kontrol edip session.seo s tAttribute("user", user) arsn kullanarak session uzerine bir kullanc c g nesnesi koymaktr. Bu Action aran login.jsp adl bir giri sayfas olac g s caktr.
... <html:form action="/login.do"> <html:text property="userName" size="20" />

99

3. Web Uygulamalar
... <html:password property="password" size="20"/> </html:form>

Sifre girilen form alan, yazlrken gzkmemesi iin html:text ile deil, html o u c g :password komutu ile alnmtr. Bu etiket zel bir Struts etiketidir, ve ifre s o s c alanlar iin kullanlr. Iine yazlan bilgiler kullanc yazarken yldz (*) olarak c gzkecektir. o u Etiket K t phanesi Tanm (TLD) u u Bir etiket ktphanesini JSP sayfalarna tantmak iin u ilem yapmamz uu c c s gerekir: 1. TLD dosyasn yaratmak 2. web.xmlden bu TLDye referans etmek 3. JSP sayfas iinde tablibi tanmlamak c TLD dosyas, alttaki gibi olacaktr.
<taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>mycompany</short-name> <uri>http://www.mycompany.com</uri> <display-name>Bilgidata TLD</display-name> <description>Bilgidata Tag Library (taglib)</description> <tag> <name>inRole</name> <tag-class>org.mycompany.kitapdemo.util.InRoleTag</tag-class> <attribute> <name>role</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>

Etiket kodunun <tag-class> ve parametrelerin <attribute> altnda tanmlanmas gerekmektedir; inRole parametresi (Java koduna tekabl edecek ekilde) <atu s tribute> altda <name> alt etiketi ile tanmlanmtr. Bu ayar dosyasn web s .xmle etiket ktphanesi olarak tantmak iin: uu c
<web-app> .... <taglib>

100

WEB KODLAMA KALIPLARI


<taglib-uri>/tags/mycompany</taglib-uri> <taglib-location>/WEB-INF/tags/mycompany.tld</taglib-location> </taglib> </web-app>

Ve son olarak, JSPden tldmizi ykleyip kullanmak iin u c


<%@ taglib uri="/tags/mycompany" prefix="mycompany" %> ... <table> <tr> <td> <mycompany:inRole role="Admin"> Bunu sadece adminler grebilir o </mycompany:inRole> </td> </tr> <tr> <td> <mycompany:inRole role="Regular User"> Bunu sadece normal kullanclar grebilir o </mycompany:inRole> </td> </tr> </table>

kullanm gerekir. Gelitirme dizin yaps altta grlebilir. s ou


+- StrutsHibLogin | +- dd | | +- META-INF | | +- tags | | | +- mycompany.tld | | | +- c-rt.tld | | | .. | | +- jboss-service.xml | | +- struts-config.xml | | +- web.xml | | +- .. | +- etc | +- lib | +- resources | | +- application.properties | | +- application_tr.properties | | +- hibernate.cfg.xml | | +- log4j.properties | | +- log4j.xml | | +- oscache.properties | +- src

101

3. Web Uygulamalar
| | | | | | | | | | | | | | | | | | | | | | | | | +- java | | +- org | | | +- mycompany | | | | +- kitapdemo | | | | | +- actions | | | | | | +- LoginAction.java | | | | | +- pojo | | | | | | +- Role.hbm.xml | | | | | | +- Role.java | | | | | | +- SimpleUserTest.java | | | | | | +- User.hbm.xml | | | | | | +- User.java | | | | | +- service | | | | | +- util | | | | | | +- InRoleTag.java | | | | | | +- ... | +- pages | | +- login.jsp | | +- main.jsp | +- sql | | +- sample_data.sql | | +- tables_mysql.sql +- build.properties +- build.xml

3.9

Ozet

Web uygulamalar yazmak iin gerekli gelitirme ortamn, MVC kavramlarn c s bu blmde iledik. JSTL, Struts etiketleri ve Struts Actionlar beraber kulou s lanlnca ok gcl bir ucl oluturmaktadrlar, zannediyorum bu potansiyeli c u u u s gsterebilmi olduk. Srekli ortaya kan Web programlama kalplarn, destek o s u c kodlar ile sunduk; Bu kalplar gncelleme, byk sonu listelerini sayfalama u u u c ile gsterme, kayt ekleme gibi kalplardr. Hatal durumlar idare etmek dier o g nemli bir husustur. Hem genelci, hem de sayfa/action bana zel durumlarda o s o nasl yaplaca bu blmde aklanmtr. Trke karakterleri idare edebilmek, g ou c s u c ve ayn uygulamadan deiik dilleri destekleyebilme hakknda yazlanlar Trkiyedeki gs u yazlmclar iin olduka faydal olacaktr zannediyorum. Bu blmde ilenen c c ou s kodlar StrutsTiles, StrutsHibSimple, StrutsHibTag ve StrutsHibAdv altnda bulabilirsiniz. Projenize rnek almanz iin en ideal kodlar StrutsHibAdv proo c jesi olacaktr.

102

Bl m 4 ou

Datk Nesneler g

Bu Bl mdekiler ou Datk nesne mimarisi g RMI JNDI EJB (Session Bean) JMS

103

4. Dagtk Nesneler zaktan nesne arma teknolojisi, uc seviyeli (three tiered) mimarilerin c g c ykseldii 90 balarnda olduka popler bir yaklam idi. U katmanl u g s c u s mimarilerde, orta katmanda bulunan ve network uzerinden arlabilen c g nyze servis eden nesnelere Uzak Metot Cars (Remote Method Invocao u g tion) ile balanlyor, bu nesnelerle bilgi alverii yapldktan sonra kullancya g s s dnlyordu. o uu Fakat takip eden yllarda Web ile ykselen Servlet odakl yeni orta katman u mimarisi ortadaki i mant katmann ele geirerek, kurumsal programclarn s g c ilgisini datk nesnelerden Servlet odakl teknolojilere evirmesine sebep olmutur. g c s Orta katmandaki i mant pr Java kodlar uzerinden, yni import ile Servlet s g u a tarafndan ayn JVM/sre iine dahil edilip arlabilen trden kodlar olduu u c c c g u g iin, artk networkden arlabilen ve uzerinde nesnelerin olduu ayr bir katc c g g mana gerek kalmyordu. Evet baz mimariler bir drdnc katman koyarak o u u hal Uzaktan Metot Cars yapmaya devam etmilerdir, fakat bu mimariler a g s hem aznlkta, hem de optimal olduklar da uphe gtrr bir durumda idiler. s ouu Gnmzde zengin nyz (rich client) teknolojilerinde hareketlenme gzkmeku u u o u o u tedir ve zengin nyzler, Java dnyasnda Swing ile ina edilirler. Ve, zengin o u u s nyz kelimesini telfuz eder etmez orta katmanda uzak nesnelerden baho u a setmemiz gerekir unk zengin nyzn HTML ureten Web orta katman ile c u o u u konumas mmkn deildir. Bu blmmzde uzaktaki bir nesneyi network s u u g ou u u uzerinden armann yollarn greceiz. c g o g Ama ondan nce neden orta katman sorusuna cevap vermemiz gerekiyor. o

4.1

Neden Orta Katman

Orta katman, uc katmanl bir mimaride nyz ile veri taban arasnda duran o u seviyedir. Servlet/JSP uzerinden HTML ureten, ya da zengin nyze servis o u eden uzak nesnelerin olduu katmann ikisi de orta katmana iyi bir rnektir. g o Eer mimarimizde orta katman bulundurmasaydk, veri eriimini direk zeng s gin nyz tarafna koymamz gerekecekti. Zengin nyzn veri tabanna direk o u o u u balant amas demek, her kullancnn veri tabanna tek bir balant amas g c g c demektir, ve kullancnn tm veriye eriim istekleri bu balant uzerinden u s g gerekletirilecektir. c s Bu yntemin avantaj, basit yapsdr; Her kullancya verilen balant uzerinden o g istenilen veri eriim ihtiyac karlanabilir. Dezavantaj, ayn ekilde, her kuls s s lancya bir balantnn almas ve o balantnn o kullancya bal kalmasdr. g c g g Her veri tabannn ezamal destekleyebildii balant says kstldr. O zaman s g g her kullancya bir balant ayrrsak, sistemizdeki ezamanl kullanc says, g s veri taban balant says limitini hibir zaman geemeyecektir. Mesel bir g c c a Linux makinasnda kurulmu PostgreSQL veri tabannn optimal ezamanl s s balant says 200 olsun. O zaman sistemde ayn anda alabilecek kullanc g c s says 200dr. Bundan daha fazla olamaz. u 104

GENEL MIMARI Bu say, tabii ki modern yksek lekli kurumsal sistemler iin ok duk u oc c c us bir saydr. Daha fazla kullancy destekleyebilmek iin modern mimarilerde c veri eriimi merkeziletirerek, taban balantlarn tek bir kiiye balamak yers s g s g ine, merkezi eriimin kontrolnde bir havuzda tutmak yolu seilmitir. Artk s u c s nyzn kendisi deil, nyze servis eden uzak nesneler ihtiyalar olduu anda o u u g o u c g balanty havuzdan alp, ileri bitince balanty havuza hemen vereceklerdir; g s g Bu sayede ezamanl taban balants kadar ezamanl ilem gerekletirilebilmi s g s s c s s olur. Zaten lekleme kstasmz bu olmaldr: Daha fazla kullancy, daha fazla oc ezamanl ilemi karlyamadan destekleyemeyiz. s s s Her kullancya tek balant verdiimiz yaklam niye verimsizdir? Bu yaklamda g g s s kullancnn dunme zaman (think time) srasnda veri taban balants hi us g c kullanlmyordu, ve bu deerli kaynan zaman israf edilmi oluyordu. Yeni g g s yaklamda balantlar ortaktr, paylalabilir, ve bir kullanc tarafndan kuls g s lanlmadklar zaman bir bakasnn kullanabilmesi iin havuzda bekliyor olurlar. s c Yeni yaklamda, kullanc dunme zaman srasnda hibir zaman veri taban s us c balants tek kullancya bal tutulmaz. g g Orta katmann bir dier faydas, kodlama disiplini asndan, grsel kodlar g c o ilem mantndan ayrmamz iin hatrlatc bir faktr olmasdr. Bu ayrm s g c o teknii, yazlm mhendislii asndan tavsiye edilen bir yntemdir, unk grsel g u g c o c u o teknolojiyi deitirdiimiz zaman, ilem mantnn ayn kalabilmesini isteriz. gs g s g Ozellikle birden fazla eit nyz teknolojisine hizmet vermesi gereken sistemc s o u lerde, ilem mantnn grsel kodlardan ayr olmas hayati nem tamaktadr. s g o o s Eer bu ayrm yaplmazsa, ilem mant kodu her nyz teknolojisi iin tekrar g s g o u c tekrar yazlyor olurdu (Kural #7 ihlli). Fiziksel olarak ayr bir orta katman a ile alnca, bu katmana gidecek kodlarn ayr olduu daha bariz olmakta, c s g ve yararl bir yazlm prensibini mimarimiz uzerinde dolayl yoldan zorlam s olmaktayz. En son olarak Hibernate, veri tabanndan okuduu nesneleri nbellekleme g o zelliine sahip olduu iin, merkezi bir orta katmann gereklilii bir kez daha o g g c g oraya kmaktadr. Onbellek, bir kullancnn istedii nesneyi, ikinci kullancya c g nbellekten servis edebildii iin, performans arttrc bir faktrdr, unk veri o g c o u c u tabanna gitme ihtiyacn azaltr. Onbellein bu ekilde kullanm iin de, iki g s c kullanc da ayn merkezi yere gitmek zorundadr (Hibernate ikinci seviye nbellei o g SessionFactory seviyesinde, her JVMde bir tane olmak uzere tutar). Bu merkezi yer de orta katmandan bakas deildir. s g

4.2

Genel Mimari

Uzak nesneler ile iletiim kurmann Java dnyasnda birok deiik yntemi s u c gs o vardr. RMI, EJB (Session Bean) ve JMS uzerinden bu iletiimi gerekletirmenin s c s yollarn bu blmde greceiz. Ama ondan nce, tm bu iletiim teknolojileri ou o g o u s uzerinden kullanabileceimiz, teknolojiden bamsz bir uzak nesne mimarisi g g greceiz. Bu mimariye, Command mimarisi adn veriyoruz. o g 105

4. Dagtk Nesneler

4.2.1

Command Mimarisi

Command kalb ilk kez Design Patterns kitabnda [2, sf. 233] Gamma ve arkadalar tarafndan ortaya konulmutur. Tam tanm yledir: Command, s s so bir istei (request), nesne olarak tanmlayan ve bize, zengin bir parametre g listesi olarak gnderebileceimiz, loga yazabileceimiz, queue uzerinde kaydo g g edebileceimiz, kendi hatasn nasl dzelteceini (undo) bilen bir birim ile g u g alabileceimiz bir mimari salar. c s g g Command kalbnn ilk k noktasnn GUI odakl hata dzeltme ilevleri c s u s (undo) olduu zannedilmektedir. Bir nesnenin nesne olmas iin alveri lisg c s s tesi metotlar gerekiyorsa [3, sf. 111], Commandn GUI iin kullanlm olmas c s anlalabilir; Hata dzeltmek, bir ilemi yapmay bilen bir nesne uzerinde eks u s lenebilecek faydal bir alveri listesi (8.2.4) ilevidir. Biz bu blmde, Coms s s ou mand kalbn datk nesneler mimarimizi desteklemek iin kullanacaz [1, sf. g c g 320]. Getireceimiz mimarinin kurallar ve kstlamalar unlar olacak. g s u 1. Onyzden servis tarafna (orta katman) yaplan her istek, bir Command nesnesi olmak zorundadr. 2. Her Command kurucu metotu kendisi iin gereken parametreleri alp c iinde saklamakla ykmldr. Olaan (default) kurucu metot ars, c u u u u g c g yanllkla arlmamas iin private tanm ile engellenecektir (Kural s c g c #3,#4) 3. Command nesnelerini iletmek, tek bir iletici nesnenin sorumluluu olas s g caktr. 4. Bir Commandn grevi, geriye bir cevap getirmek ise, bu cevap Como mand nesnesinin iinde tutulacak, ve bu cevap nesnelerine get eriimi c s salanacaktr. g 5. Command nesneleri, pr Java nesneleri olacak, hibir iletiim teknolojiu c s sine (EJB Session Bean, JMS, RMI) baml yazlmayacaklardr. g CommandHandler Command mimarisinin datk mimarilere getirdii faydalar nedir? Birincisi, g g servis tarafna CommandHandler uzerinden tek bir giri noktas salanmasdr. s g Cok yzllk (polymorphism) sayesinde, ust seviye Command classndan mi u uu ras alan (inherit) alt seviye i yapc Command nesneleri, kendilerini sadece s Command arayz uzerinden gren bir CommandHandler tarafndan, merkezi u u o bir yerde iletilebiliyor hle gelirler (Sekil 4.1). Bu tek merkez, uzaktan ar s a c g teknolojisi deitirilmesi gerektiinde tekrar yazlacak yegne noktadr! Eer gs g a g EJB Session Beanden JMSe geiyorsanz, sadece CommandHandler JMS ile c ileyecek hle getirebilirsiniz, ve bundan sonra tm servis taraf mimariniz s a u JMSte almaya balayacaktr. c s s 106

GENEL MIMARI

Command
+execute()

executes

CommandHandler
+executeCommand(command:Command): Command

AddCarCommand
+AddCarCommand(car:Car,garageId:String) +execute(): Command

GetGarageCommand

Sekil 4.1: Command Nesne Yaps

Client

Server

CommandHandler

create()

execute()

Command

Command

Sekil 4.2: Network Uzerinden Command Gnderimi o

107

4. Dagtk Nesneler Ayrca, bu tek giri noktasnda, tm ilemler iin gerekli olabilecek trden s u s c u ek ilemleri rahatlkla yerine getirebiliriz. Mesel her istek sonucunda Hibers a nate oturumunu kapatmak, bir Commandden gelebilecek hatalar yakalayp Hibernate transaction geri sarmak (rollback), ya da her Command iin bir iletici c s (worker) Thread balatmak gibi ek iler, bu tek merkezi noktada yaplabilir. s s Eer, klasik her istek iin ayr bir metot yntemini takip ediyor olsaydk, tm g c o u ilemlere lzm olan ek ilemleri merkezi bir yerde yapmak daha zor olurdu. s a s Evet, Spring Framework Interceptor teknii kullanarak her metot iin kendi g c istediimiz ek kodlar engel kod takarak iletebilirdik, fakat bu ek, teknoloji g c s orbasna bir teknoloji daha eklemi olacak, Spring ayar dosyasn fazla iirecek, c s ss hem de, zten paketlenmi bir istek (Command) bekleyen JMS seenei iin a s c g c tamamen gereksiz olacakt. Command Nesneleri Command classlarnn basit Java nesneleri olduundan bahsetmitik. Bunun g s ustne, bir Command Serializable da olmaldr, unk Commandler net u c u work uzerinden gnderilirken ierikleri bozulmadan gidebilmelidirler. Tm Com o c u mandlerin Serializable olmas iin bu arayzden en ust seviyede miras almak c u gerekiyor.
public interface Command extends Serializable { public void execute() throws Exception; }

Her zel Command, Command ust snfndan miras ald iin artk otomatik o g c olarak Serializable olacaktr. Her zel Commandn ilem mant iin yapmas gerekenler, o Commandn o s g c execute metotu iinde kodlanr. Command iin gereken parametreler, bir kuc c rucu metot uzerinden verilmelidir. Geri dnmesi gereken deerler ise, Com o g mand classnn i eleri olarak tutulmaldrlar. Ornek olarak GetCarCommand c og kodlarn grelim. o
public class GetCarCommand implements Command { String licensePlate; Car car; public Car getCar() { return car; } public GetCarCommand(String licensePlate) { this.licensePlate = licensePlate; }

108

RMI
public void execute() throws Exception { Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); car = (Car)s.get(Car.class, licensePlate); } }

Hibernate transactionn commit edilmesi ve oturumun kapatlmas ilemlerinin s Command iinde yaplmyor olmas belki dikkatinizi ekmitir. Bu ilemler, c c s s merkezi bir yerde (CommandHandler) yapldklar iin, ayrca Command iinde c c tekrarlanmarlna gerek yoktur. Bu blmn geri kalan ksmnda, RMI, EJB (Session Bean) ve JMS teknoloou u jilerini teker teker tanyacaz. Her teknolojiyi ilk ele aldmzda, nce bize g g o verdii datk nesne zelliklerini greceiz. Daha sonra, Command mimarisini g g o o g alp, bu yeni datk teknoloji uzerinden almasn salayacaz. Bu blm g c s g g ou bittiinde, elimizde uc deiik teknolojiyle alabilecek bir mimari yapmz g g s c s olacak. Bu yap yledir ki, bir uzaktan arma teknolojisinden dierine proo c g g jenin ortasnda bile geebilme ansn elde edeceksiniz. Bu tr bir esnekliin, c s u g her proje iin faydal olacanz dunyoruz. c g us u

4.3

RMI

RMI, Uzak Nesne Cars (Remote Method Invocation) Java dnyasnda ilk g u uzak nesne ar sistemidir. Kullanm asndan en basit ve servis nesneleriniz c g c uzerinde en az kst getiren teknoloji RMIdr. Salad yetenek olarak, RMI ile uzaktaki bir nesneye network uzerinde g g ar yapabilme zelliine kavuuyoruz. Onemli bir nokta, bu servis nesnesinin c g o g s tekil nesne (singleton) olacadr. Yni RMI birok balanan mterinin arlarn, g a c g us c g tek bir nesneye ynlendirir. Herkesin ayn objeyi kullanacak olmas, servis o tarafnn ok threade hazr (thread-safe) olmasn gerektirir. c Servis tarafnda metotlar ileten Threadlerin nasl alaca urn gelitiricisine s c s g u s braklmtr. Bu sebeple projenizde Thread politikasn kendinizin belirlems enizi tavsiye ediyoruz. Her gelen istek iin yeni Thread balatmak, bir Thread c s politikas olabilir. Bir nesneyi RMI uzerinden kullanma amak iin, bir arayz (interface) bir c c u de gerekletirim (implementation) kodu gerekir. Arayz bildiimiz Java inc s u g terface kelimesi ile tanmlanan arayzdr. Gerekletirim bu arayz alr, ve u u c s u u her metotun iler kodunu tanmlar. RMI iin, eski yntemde, rmic adl bir kos c o mut satr programn arayz ve gerek kod uzerinde ileterek, iinde network u c s c kodlar tayan ve Stub ve Skeleton olarak bilinen iki class uretilmesini gereks tiriyordu. Biz, RMI teknolojisini Spring Framework uzerinden kullanacaz. g 109

4. Dagtk Nesneler

4.3.1

Spring

Spring Framework, J2EE kullanmn basitletirmeyi ve amalayan bir altyap s c projesidir. Springden bahsedilirken iki terimi srekli duyacaksnz: Spring bir u IoC kabdr ve Spring AOP yapmanza izin verecektir. AOP, bildiimiz gibi, birden fazla obje, tip, metota uygulanabilecek kod g paralarnn nesnesel bir ekilde deil de engel takar gibi koda nesne dndan c s g c s eklemlenebildii bir programlama eklidir. Sonradan eklenebilen bu kodlara g s AOP dnyasnda Aspect deniyor. Klasik rnek loglama rneidir; Loglama, her u o o g kodun iine direk konmas yerine, AOP dnyasnda bir Log Aspecti yaratlr, ve c u mesel her metotun banda uygulanabilecek bir Aspect uzerinden d loglama a s s kodunun arlmas salanr. Kodunuza sonradan taklan bu engelin ilem c g g c s annda arlmas, AOP kabnn sorumluluudur, yni nesnelerinizin ileyii c g g a s s ilem annda AOP sistemi tarafndan izleniyor olacaktr. Hayal edebileceiniz s g gibi arka planda mthi baytkod cambazlklar dnmesi gerekecektir. u s o IoC, Ingilizce Inversion of Control kelimelerinin ksaltlmdr, yni Kons a troln Tersine Cevirilmesi anlamna gelir. Burada anlatlmak istenen, prou gramcnn bir nesneyi/kayna gidip bulmas ya da new ile yaratmas yerine, o g nesnenin/kaynan bir isim ile bir ayar dosyasnda tanmlanmas ve Springin g bu nesneyi o tanma gre yaratmas, sonra da bu nesneyi sizin tarif ettiiniz bir o g referans deikenine set etmesidir. Yni siz almyorsunuz, size takdim ediliyor. gs a Kontroln tersine evirilmesi tanm ite buradan gelmektedir. Daha detaya u c s inmek gerekirse (kod balamnda) bahsedilen referans deikeni, o referans g gs kullanacak ilem mant nesnesinin iinde yer alr. Bu referansa set eden bir s g c

RMI Client

RMI Server

SubtracterService

AdderService

Sekil 4.3: RMI 110

RMI metotu programc yazm olmaldr, unk Spring, Java Reection kullanarak s c u (ve ayar dosyasndaki referans ismine gre) belirlenen set metotunu arr o c g (program banda ve dinamik olarak). s Ayrca Spring, size sadece baz anlamda AOP ve IoC zellikleri salayan bir o g paket deil, tm J2EE servislerinin ve gzde ak yazlm paketlerini, IoC ve g u o c AOP uzerinden kullanmanz salayan bir arac servistir. Springi yazan pro g gramclar, hem bir IoC/AOP kab yazm, hem de ek olarak bu temel kab kullas narak J2EE arayzleri/servisleriyle Ioc/AOP kabn teker teker balayarak bir u g ek seviye daha ortaya karmslardr. Springi Spring yapan esas seviye budur. c Spring, J2EE servislerini IoC/AOP uzerinden sunmaktadr; Mesel bir J2EE a xyz servisi size takdim edilen bir nesne olacaktr, ya da, tm nesnelerinize uyguu lanabilecek J2EE Aspectleri olarak karnza kacaktr. s c

4.3.2

Basit Bir RMI/Spring Ornei g

RMI servisi iin bir Spring sarmalayc IoC servisi vardr. Servis tarafnda c RmiServiceExporter, aran tarafnda RmiProxyFactoryBean uzerinden bac g sit Java interfaceinizi, kodunuzdan tek RMI arayz rmadan RMIa hazr u u cag hle getirebilirsiniz! Servis tarafnda: a Liste 4.1: ServerInterface.java
public interface ServerInterface { public int add(int a, int b); }

Liste 4.2: ServerImpl.java


public class ServerImpl implements ServerInterface { public int add(int a, int b) { return a + b; } }

Liste 4.3: springServer.xml


<beans> <bean id="servis" class="org.vs.vs.ServerImpl"/> <bean class="org.springframework.remoting.rmi.RmiServiceExporter"> <property name="serviceName"><value>AdderService</value></property> <property name="service"><ref bean="servis"/></property> <property name="serviceInterface"> <value>org.vs.vs.ServerInterface</value> </property> <property name="registryPort"><value>41199</value></property> </bean>

111

4. Dagtk Nesneler
</beans>

Grldgu gibi gerek kod (implementation) ServerImpl nesnesi Springde o u u c servis olarak isimlendirilmi. Daha sonra bu isim, yani nesne, RmiServices Exporter adl, rmic yerine geecek olan Spring bysn yapacak yardmc c u uu u classa geilmi. Spring bu tanmlar kullanarak J2EE standartna uyumlu bir c s network servisi AdderServicei yaratacaktr. Bu servis objesi uzerinde gerekli tm RMI kod uretme ilemleri yaplm, ve networkden kullanma hazr hle u s s a gelmitir. Dikkat ederseniz, btn bunlar yapabilmek iin servis taraf kodus uu c muz iinde tek bir RMI API armamz gerekmedi. Ayrca, normal artlarda c c g s build.xml iinde gerekecek rmic ile yaplan Stub/Skeleton uretim ilemi de c s artk tamamen Spring tarafndan yaplmaktadr (koma zamannda ama, uygus lamann banda ve bir kere olduu iin hibir performans fark hissedilmeyes g c c cektir). Servis tarafnda bu objeyi aktif hle getirmek iin, balang srasnda u a c s c s arlar yapabilirsiniz. c g
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {"springServer.xml"});

Caran tarafta ise g Liste 4.4: springClient.xml


<beans> <bean id="remoteServer" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> <property name="serviceUrl"> <value>rmi://localhost:41199/AdderService</value> </property> <property name="serviceInterface"> <value>org.vs.vs.ServerInterface</value> </property> </bean> </beans>

Burada grldu gibi, uzaktaki ServerImpl nesnesini armak iin hibir o u ug c g c c RMI koduna ihtiya duymadk. Normlde Naming.lookup gerektiren nesne c a bulmak ilemi, sadece Spring tanmlar ile RmiProxyFactoryBean uzerinden s yaplmaktadr. Springin network uzerindeki AdderServiceine eriebilecek bir s nesne yaratabilmesi iin, ona gereken tm interface ve network eriim bilgic u s leri springClient.xml tanm dosyas iinde tanmldr. Bu bilgileri kullanarak c servise balanacak kod paras altta gsterilmitir. g c o s
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {"springClient.xml"}); BeanFactory factory = (BeanFactory) appContext; AdderService as = factory.getBean(remoteServer);

112

RMI Ayar dosyas springClient.xml iinde belirtilen port deerinin springServer c g .xml iindeki port deerine uymas mecburidir. Bu portlar, RMI kayt (regc g istry) portudur. Tm objelerin kayt edildii merkezi kayt nesnesinin servis u g edildii port adresidir. g

4.3.3

RMI ve Command Mimarisi

Simdi, blm 3de tarif edilen ve StrutsHibAdv kodlarnda temsil edilen ara ou balar ve garajlar rneini, RMI ve Command mimarisine geireceiz. Kodlarn o g c g tamamlanm hlini CarsRMI dizini altnda bulabilirsiniz. s a Bu blmn giriinde, zengin nyzler szkonusu olduunda Command miou u s o u o g marisinin orta katmandaki Web kodlarnn yerini aldn sylemitik. Hem g o s Web, hem servis nesneleri birarada olmuyordu. Bu blmn geri kalannda, ou u sadece rnek amal olarak, Web kodlarmz servis nesneleri ile konuturacaz. o c s g Bunun sebebi, rnek kodlarmz iin Swing teknolojisine girmek istemeyiimizdir. o c s Hem elde mevcut olan kodlar kullanmak, hem de pr Struts bazl kodlara servis u nesne destei ekleyince hangi noktalarn deitiini grmek iin, ziksel mimari g gs g o c asndan optimal olmayan yapacaz. CarsRMI projemiz, drt katmanl olacak. c g o Command mimarisini RMIa geirirken, uzaktan arlmaya amamz gereken c c g c tek class CommandHandler olacak. CommandHandler Liste 4.5: CommandHandler.java
public interface CommandHandler { public Command executeCommand(Command command) throws Exception; }

Liste 4.6: spring.xml


<beans> <bean id="commandHandlerImpl" class="org.mycompany.kitapdemo.service.CommandHandlerImpl" /> <bean class="org.springframework.remoting.rmi.RmiServiceExporter"> <property name="serviceName"><value>CommandHandler</value></property> <property name="service"><ref bean="commandHandlerImpl"/></property> <property name="serviceInterface"> <value>org.mycompany.kitapdemo.service.CommandHandler</value> </property> <property name="registryPort"><value>3045</value></property> </bean> </beans>

113

4. Dagtk Nesneler CommandHandler arayzn gerekletiren CommandHandlerImpl class uzerinde, u u u c s executeCommand aadaki gibi olacak. s g Liste 4.7: CommandHandlerImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

package org.mycompany.kitapdemo.service; import org.apache.log4j.Logger; import org.hibernate.HibernateException; public class CommandHandlerImpl implements CommandHandler { private Logger logger = Logger.getLogger("appLogger"); public Command executeCommand(Command command) throws Exception { final Command param = (Command)command; final Exception ex[] = {null}; // her yeni ilem iin bir Thread a s c c Thread t = new Thread (new Runnable() { public void run() { try { param.execute(); HibernateSession.commitTransaction(); } catch (HibernateException exx) { HibernateSession.rollbackTransaction(); ex[0] = exx; } catch (Exception exx) { HibernateSession.rollbackTransaction(); ex[0] = exx; } finally { HibernateSession.closeSession(); } } }); synchronized (this) { t.start(); try { t.join(); } catch (Exception e) { } if (ex[0] != null) { throw ex[0]; } } return command; } }

Satr satr aklama: c 114

RMI 11: Metota gelen command referans, final olarak tanmlanm baka s s bir referansa transfer edilmelidir. Bunun sebebi, biraz altta bu referansa c eriecek bir i class (inner class) olmasdr. I class deiken eriim kurals c gs s larna gre, dardan eriilecek tm referanslar, final olarak tanmlanmaldr. o s s u Eer bu yaplmazsa, alttaki gibi bir hata alnr: local variable comg mand is accessed from within inner class; needs to be declared final 12: Command iletirken ortaya kabilecek Exceptionlar i classn s c c dna tayabilmek iin, bir Exception dizini tanmlyoruz. Niye sadece s s c basit bir Exception referans deil? Cunk, i class iinden, dardaki g u c c s bir referansa erimemiz gerekirse bu referans final olmaldr. Final olan s bir referansa = ile hibir ey set edemeyiz! Ama bu engele tkanp kalmak c s c yerine, bir hack ile ii zyoruz: I classtan bir referansa set edemesek s co u te, final olan bir dizin iine atama yapmak, hla legal bir harekettir. c a Biz de Exception yerine Exception[] kullanarak problemi zyoruz. co u 15,16: Runnable arayzn gerekletiren bir class annda oluturup, u u u c s s annda Thread nesnesine alstrlmaya hazr olarak veriyoruz. Bu kulc lanm, biraz norml d bir kullanmdr, fakat yeni bir Thread tarafndan a s iletilecek kodlar ayn kod sayfasnda grebilmek iin ok gzel bir tekniks o c c u tir. Alternatif olarak, ayn kod blounu ayr bir dosyaya ve classa koyup g ve Threade bu class verebilirdik, ama bu, kod idaresi iin pek faydal c olmazd. o 17-20: Ilk nce Command iletilir, ve iler yolunda gitti ise (hi Exception s s c atlmamsa) transaction commit edilir. s 20-23: Hibernate tarafndan atlan bir hata var ise, burada yakalanr. Bu durumda, transaction geriye sarlmal (rollback) ve ele geen hata ex c dizini uzerine yazlmaldr. 23-26: Burada Hibernate hatas deil, daha genel bir hata olmutur. g s Yaplan hata karlama hareketleri yine ayndr, burada ayr bir blm ols ou masnn sebebi, ileride deiik hata karlama ilemlerini burada yaplabilecek gs s s olmasdr. En azndan her catch kendi log ifadelerini yazarak, ne tr bir u hata meydana ktn servis taraf loglarnda gsterebilir. c g o 26-28: Hata olsa da olmasa da ileyecek finally blou iinde Hibernate s g c oturumu kapatlr. 39: Command iletildikten sonra geri dndrlr. Bu ok nemlidir unk geriye s o u uu c o c u sonu dndrmesi gereken Commandler, sonu deerlerini yine kendi c o u c g uzerlerinde saklayacaklar iin, ayn Commandin geri dnmesi ok nem c o c o lidir. Caran tarafta istedii deerlere erimek isteyenler, Command uzerinde g g g s get arlar yaparak servis tarafndan gelen sonulara eriebilirler. c g c s 115

4. Dagtk Nesneler Caran Taraf g Caran (Web) tarafnda Spring tanm alttaki gibi olacaktr. g
<beans> <bean id="commandHandler" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> <property name="serviceUrl"> <value>rmi://localhost:3045/CommandHandler</value> </property> <property name="serviceInterface"> <value>org.mycompany.kitapdemo.service.CommandHandler</value> </property> </bean> </beans>

Bu tanm sayesinde, getBean kullanarak gereken her yerde CommandHandler referansn alabiliriz. Eer bu referansn almn hzlandrmak istiyorsak, Strutg s/Web ortamnda, bu referans oturum uzerinde srekli hazr tutabiliriz, ve u gerekince getAttribute ile oradan alrz. CommandHandler Referansn hazrlamak ve set etmek iin bir Servlet ltresi c yazmamz gerekiyor. Bu ltre, her Web istei banda oturum uzerinde bir g s CommandHandler referans olup olmadn kontrol eder. Eer yoksa, factory g g .getBean ile bir tane alr ve oturum uzerine koyar. Liste 4.8: ServiceReferencesFilter.java
public class ServiceReferencesFilter implements Filter { private Logger logger = Logger.getLogger("appLogger"); public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession(); if (session.getAttribute("commandHandler") == null) { CommandHandler commandHandler = (CommandHandler)AppStartup.factory.getBean("commandHandler"); session.setAttribute("commandHandler", commandHandler); } chain.doFilter(request, response); }

116

RMI
public void destroy() { } }

Artk her Struts Actioni iinden ComnmandHandler referansna eriebiliriz. c s Struts Action, servis ile iletiime gemesi gerekince, gereken Commandi new ile s c yaratr, CommandHandlera network uzerinde gnderir, ve Commandn iletilmesini o s salar. g Liste 4.9: ShowCarDetailAction.java
public class ShowCarDetailAction extends Action { private static Logger logger = Logger.getLogger("appLogger"); public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { CommandHandler handler = (CommandHandler)request.getSession().getAttribute("commandHandler"); String licensePlate = request.getParameter("licensePlate"); GetCarCommand cmdGet = new GetCarCommand(licensePlate); Command resGet = handler.executeCommand(cmdGet); Car car = ((GetCarCommand)resGet).getCar(); DynaActionForm daf = (DynaActionForm) form; BeanUtils.copyProperties(daf, car); if (car.getGarage() != null && !car.getGarage().equals(new Integer(0))) { daf.set("garageId", car.getGarage().getGarageId()); } request.getSession().setAttribute("car", car); // .... return mapping.findForward("success"); } }

Car nesnesi setAttribute ile oturum uzerine konduktan sonra, JSP sayfas arabann detaylarn gsterecektir. o 117

4. Dagtk Nesneler

4.4

JNDI

Birazdan ileyeceimiz EJB ve JMS teknolojilerini kullanmak iin, JDNI adl s g c bir teknolojiye ihtiyacmz var. JNDI biraz daha yakndan tanyalm. JNDI (Java Naming and Directory Interface) arayzleri, deiik trden u gs u dizin (directory) ve isimlendirme (naming) servislerine standart bir arayz u salar [4, sf. 24]. Bu adan JNDI, JDBCye benzer. Aynen JDBCnin deiik g c gs trden veri tabanlar ile konumamz salad gibi, JNDI da dizin ve isimu s g g lendirme servisleri olan LDAP, Novel Netware NDS, CORBA Naming Service ve irketlere zel (proprietary) isimlendirme servislerine erimemizi yardmc s o s olur. JBoss iinde de JNDI standart arayzleri uzerinden eriebileceimiz JBossa c u s g zel bir dizin ve isimledirme servisi vardr. o JNDI uzerinden birok deiik servise eriebilirsiniz. Bu servisler, bir JMS c gs s Queuesu, bir Session Beani, ya da ziksel bir yazc bile olabilir. Yni JNDI, bir a servis ile bir ismi birbirine ilintilendirerek, o servise o isim uzerinden eriebilmenizi s salar. g RMI blmnde, uzaktaki bir nesneye erimek iin JNDIa konusuna girmemiz ou u s c gerekmedi, unk hem servis hem balanan taraf Spring uzerinden hallediyc u g orduk. Spring, JDNI ilemlerini kapal kaplar arkasnda kendisi hallettii iin s g c bizim fazladan JNDI ilemi yapmamza gerek kalmamt. Fakat, grmek uzere s s o olduumuz EJB ve JMS teknolojileri iin JNDI kullanacaz, unk JMS ve g c g c u EJB teknolojilerini pr hlde kullanyoruz (bylesi daha kolay olacak). EJB u a o balamnda JDNI, bir Session Beani ismiyle bulmak iin, JMS iin ise bir g c c Queueya ismini kullanarak eriebilmek iin kullanacaz. s c g JBoss iin standart JNDI kodlama kalbmz yle olacak: c so
import import import import import import ... InitialContext ic = null; Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces"); p.put(Context.PROVIDER_URL, "localhost:1099"); // JNDI port 1099 ise try { ic = new InitialContext(p); Object objref = ic.lookup("buraya/jndi/ismi/yazilir"); // ... javax.naming.InitialContext; javax.naming.NamingException; java.util.Hashtable; javax.naming.Context; java.util.Properties; java.util.List;

118

EJB Session Bean


// burada elde edilen referans ile ilemler yaplabilir s } catch (Exception e) { // hata durumunu rapor et e.printStackTrace(); }

Ornekte kullandmz JNDI portu, 1099 numaral porttur. Fakat bu port g deeri baz JBoss kurulularnda deiik olabilir (paketten kan hli, 109 g s gs c a 9 olmak uzere ayarldr). Gerek JNDI portunuz deiik ise, bu deiik deerin c gs gs g ne olduunu anlamak iin JBoss alrken baslan log mesajlarna bakmanz g c c yeterli olacaktr. Ornek bir JBoss log ekran aada gsterilmitir. s g o s
16:53:57,287 INFO [Server] Starting General Purpose Architecture (GPA). 16:53:58,539 INFO [ServerInfo] Java version: 1.4.2,Sun Microsystems Inc 16:53:58,549 INFO [ServerInfo] Java VM: Java HotSpot(TM) Client VM 1.4. n Microsystems Inc. 16:53:58,549 INFO [ServerInfo] OS-System: Windows XP 5.1,x86 16:53:59,250 INFO [Server] Core system initialized 16:54:02,395 INFO [WebService] Using RMI server codebase: http://bio:80 16:54:03,126 INFO [NamingService] Started jndi bootstrap jnpPort=1099, 1098, backlog=50, bindAddress=/0.0.0.0, Client SocketFactory=null, Serve Factory=org.jboss.net.sockets.DefaultSocketFactory@ad093076 16:54:11,338 INFO [Embedded] Catalina naming disabled 16:54:12,710 INFO [Http11Protocol] Initializing Coyote HTTP/1.1 on http -8080

Bu mesaj satrlar iinde jnpPort ibaresinin verildii satra baknz. Eitliin c g s g sandaki deer, JBossun JNDI servisi iin kulland port deeridir. g g c g g

4.5

EJB Session Bean

EJB teknolojisi, uc deiik ksmdan meydana gelir. g s Konumlu (Stateful) Session Bean (SFSB) Konumsuz (Stateless) Session Bean (SLSB) Entity Bean Bu seeneklerden Entity Bean teknolojisi, EJBnin programclar tarafndan c en tepki eken ve kabul grmeyen ksm olmutur. Kalclk (persistence) probc o s lemini zmeye alan Entity Beanler, zdklerinden daha fazla problemi co c s co u beraberlerinde getirmilerdir. Entity Bean teknolojisi, Kural #1, #5 ve #6in s ok ciddi ekilde ihllleridir. c s a Fakat, SFSB ve SLSB bileenleri datk mimarilere faydal olabilirler. Ozels g likle, JBoss Uygulama Servisinin Session Beanlere salad kmeden kurg g co tulma (failover), yk datm (load balancing) servisleri sayesinde, salam ve u g g leklenebilen Session Bean bazl sistemler kurmak mmkndr. oc u u u 119

4. Dagtk Nesneler

4.5.1

Sonu Dizin Yaps c

JBoss uzerinde bir EJByi iletmek iin deploy dizininde kurulmas gereken s c dizin yaps altta gsterilmitir. o s
+- kitapdemo.ear | +- META-INF | | +- MANIFEST.MF | | +- application.xml | | +- jboss-app.xml | +- conf | | +- log4j.xml | +- kitapdemo.sar | | +- META-INF | | | +- MANIFEST.MF | | | +- jboss-service.xml | | +- conf | | +- activation.jar | | .. | | +- xml-apis.jar | +- hibernate.cfg.xml | +- kitapdemo.jar | | +- META-INF | | | +- ejb-jar.xml | | | +- jboss.xml | | | +- MANIFEST.MF | | +- org | | | +- mycompany | | | | +- kitapdemo | | | | | +- dao | | | | | +- pojo | | | | | | +- Car.class | | | | | | +- Car.hbm.xml | | | | | | +- Garage.class | | | | | | +- Garage.hbm.xml | | | | +- service | | | | +- util

Bu yap, rnek projelerin build.xmli tarafndan otomatik olarak kurulacaktr. o

4.5.2

SFSB ve SLSB

Eer uzaktan ar yaptmz Session Bean bir SFSB ise, o Beane elimizde g c g g bir referans olduu srece, o Bean muhafaza edilir. SFSBlerde, aynen new ile g u yaratlan Java nesnelerindeki gibi, bir nceki yaplan ar bir sonrakini etkiler o c g unk eldeki SFSB, JBoss tarafndan sabit/ayn tutulur. Kyasla eer eldeki c u g referans bir SLSBe iaret ediyor olsayd, JBoss Uygulama Servisi konumsuz s olarak bildii bu nesneyi iki ar arasnda deitirebilirdi. g c g gs 120

EJB Session Bean Peki Uygulama Servisi bu SLSB deitirmesini niye yapar? Genellikle elde gs bir SLSB havuzu vardr ve gelen her yeni istek iin havuzdan bir nesne alnp c ar uzerinde yaplr ve nesne havuza geri konulur. Onceden yaratlm ve c g s havuzdan servis edilen nesnelerin tekrar bir new aamasndan gemesi gereks c mez, ve hazr olan nesnelerin servis edilmesinin daha hzl olduu savunulduu g g iin bu yap seilmitir. Havuzdan alma, havuza geri koyma ilemi, her yeni c c s s arda yaplabilir, unk nesneler konumsuzdur; Bir ar, bir sonrakini etkc g c u c g ilemez. Tabii EJB belirtimleri (specication) aslnda havuzlamadan bahsetmiyor; Belirtim sadece, SLSBler arlrken ayn nesnenin orada olacana gvec g g u nilmemesinden bahsetmektedir (SFSB iin ise tam tersi geerlidir). Havuz kulc c lanp kullanmama gibi detaylar, her ticari uygulama paketinin kendi seimine c braklmtr. s

4.5.3

SFSB

Kodlama asndan bir SFSB iin, uc tane class yazlmas gerekiyor. Bunc c lar Home, Remote arayzleri, ve gerekletirim kodlardr. Bu blmde rnek u c s ou o olarak MyTestSession adnda bir SFSB yazacaz. Bu Bean uzerinde increg ment ve getCount adl iki metot olacak. Increment metotunu kullanarak SFSB uzerindeki bir saya deeri arttrabileceiz, getCount ile mevcut saynn okun c g g mas mmkn olacak. Bu rnein ok uygun bir Konumlu (stateful) Session u u o g c Bean rnei olduunu herhalde anlamsnzdr, eer MyTestSession konumlu o g g s g deil konumsuz bir Bean olsayd, arttrdmz deerlerin hatrlanmas mmkn g g g u u olmazd. Zaten SFSB ve SLSB arasndaki fark anlamak iin bu deitirmeyi c gs gstereceiz. o g Kod, alttaki gibi olacak (bitmi kodlar ve Ant build.xml dosyasn Couns terStateful projesi altnda bulabilirsiniz):
public interface MyTestSession extends javax.ejb.EJBObject{ public void increment() throws java.rmi.RemoteException; public int getCount() throws java.rmi.RemoteException; } public interface MyTestSessionHome extends javax.ejb.EJBHome { public MyTestSession create() throws javax.ejb.CreateException, java.rmi.RemoteException; } public class MyTestSessionBean implements SessionBean { int counter = 0; public void ejbCreate() throws CreateException { }

121

4. Dagtk Nesneler

public void setSessionContext( SessionContext aContext ) throws EJBException {} public void ejbActivate() throws EJBException { } public void ejbPassivate() throws EJBException { } public void ejbRemove() throws EJBException { } public void increment(){ counter++; } public int getCount(){ System.out.println(counter); return counter; } }

Bu kodlarn deploy edilmesi iin ejb-jar.xml, jboss.xml, application. c xml, jboss-app.xml ve jboss-service.xml adnda be dosya gerekmektedir. s Tm bu dosyalara teker teker bakalm (jboss-service.xmli daha nce 3.3.3 u o blmnde ilemitik). ou u s s Liste 4.10: jboss-app.xml
<jboss-app> <module> <service>kitapdemo.sar</service> </module> </jboss-app>

Liste 4.11: application.xml


<application> <display-name>KitapDemo</display-name> <description>KitapDemo Queue</description> <module> <ejb>kitapdemo.jar</ejb> </module> </application>

Liste 4.12: ejb-jar.xml


<ejb-jar> <description>Kitapdemo</description> <display-name>Kitapdemo</display-name> <enterprise-beans> <!-- Session Beans --> <session> <display-name>My Test Session Bean</display-name>

122

EJB Session Bean


<ejb-name>test/MyTestSession</ejb-name> <home>org.mycompany.kitapdemo.service.MyTestSessionHome</home> <remote>org.mycompany.kitapdemo.service.MyTestSession</remote> <ejb-class> org.mycompany.kitapdemo.service.MyTestSessionBean </ejb-class> <session-type>Stateful</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> <assembly-descriptor> </assembly-descriptor> </ejb-jar>

Liste 4.13: jboss.xml


<jboss> <enterprise-beans> <session> <ejb-name>test/MyTestSession</ejb-name> <jndi-name>ejb/test/MyTestSessionBean</jndi-name> </session> </enterprise-beans> <resource-managers> </resource-managers> </jboss>

Grldu gibi application.xml ve jboss-app.xml olduka basmakalp dosyalardr. o u ug c Her proje iin bir kez yaratlrlar, ve hibir EJBye has bir tanm iermezler. c c c Bu iki dosyann amac, EJB kodlarnn bulunduu JAR ve SAR dosyalarnn g isimlerini EAR paketine tantmaktr. Her EJBye zel ayarlarn yapld yer ejb-jar.xml dosyasdr. Mesel eer o g a g EJBnin konumsuz olmasn istersek, yukardaki <session-type> etiketi iinde c Stateful yerine Stateless kelimesini kullanabilirdik. EJB tanmlamas hazrsa, ejb-jar.xml iindeki Session Bean tanmn bir c JNDI ismine balayan yer de jboss.xml dosyas olacaktr. Bu dosyaya gre, g o EJBmizin JNDI uzerinden bulunabilecei isim ejb/test/MyTestSessionBean g ismi olarak belirtilmitir. s Simdi JNDI uzerinden MyTestSessionBean EJBsini bulan ve ar yapan c g balant kodunu grelim. g o Liste 4.14: Mainline.java
public class Mainline { public static void main(String[] args) { MyTestSession beanRemote;

123

4. Dagtk Nesneler
InitialContext ic = null; Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces"); p.put(Context.PROVIDER_URL, "localhost:1099"); // JNDI port. try { ic = new InitialContext(p); Object objref = ic.lookup("ejb/test/MyTestSessionBean"); MyTestSessionHome testSessionBean = (MyTestSessionHome) PortableRemoteObject.narrow(objref, MyTestSessionHome.class); beanRemote = testSessionBean.create(); while (true) { beanRemote.increment(); System.out.println("Count is : " + beanRemote.getCount()); try { Thread.currentThread().sleep(1000); // uykuya yat } catch (Exception e) { } } } catch (Exception e) { e.printStackTrace(); } } public Mainline() { } }

Test kodumuzda nce JNDI uzerinden MyTestSession bulunuyor, daha sonra o bu referans uzerinden, sonsuz bir dng iinde SFSB uzerindeki saya bir o u c c arttrlp, yeni deer ekrana baslyor. SFSB iindeki servis kodunu hatrlarsanz, g c ekrana basma ilemi hem servis hem de aran tarafnda yaplmaktadr. Nars c g row ve create arlar olduka basmakalp arlar olduklar iin detaylarna c g c c g c inmeyeceiz. Her EJB iin ezbere takip edilmesi gereken metotlardr. g c Caran Taraf ve Import g Bu noktada nemli bir soru, gelitirme ortam asndan, aran taraf kodo s c c g larnn MyTestSessionHome ve MyTestSession class tanmlarna nasl sahip olduudur. Yni importlar iin gereken .class dosyalar nereden gelmitir? g a c s Bu sorunun nemi, aran ve arlan tarafn bazen apayr projeler olabilmesi o c g c g durumunda daha da kuvvetle ortaya kacaktr. c Bu soruna ozm olarak, servis taraf kodlarnn derlemesi bittikten hemen c u sonra, servis taraf build.xmli iinden, servis taraf tm classlar bir jara c u 124

EJB Session Bean koyarak, aran projenin lib dizini iine kopyalamak uygundur. Bu kopyc g c alama ileminin rneini, CarsEJB/Server projesindeki build.xml iinde gres o g c o bilirsiniz. Gereken classlar CarsEJB/Serverden, CarsEJB/WebClient/lib altna kopyalanmaktadr.

4.5.4

EJB ve Command Mimarisi

SFSB uzerinden Command mimarisi kullanmak iin, 4.1 blmnde bahsedildii c ou u g gibi, tek EJBletirmemiz gereken yer CommandHandler kodu olacaktr. Bu s nokta, servis tarafna networkden giri noktas olduu iin, uzaktan arlacak s g c c g tek noktadr. Bunun haricinde, eer RMI bazl Command mimarisini anlattmz g g 4.3.3 blmndeki Command ve alt snarn olduu gibi alp kullanmak isou u g tersek, bunu yapabiliriz, unk Command classlar hibir teknolojiye bal c u c g yazlmamtr! s Simdi yeni CommandHandler kodlarn grelim (EJBye geerken, EJB stili o c isimlendirmeyi takip etmek iin bu classa CommandHandlerBean ismini vereceiz). c g
public interface CommandHandler extends javax.ejb.EJBObject { public Command executeCommand(Command command) throws java.rmi.RemoteException; } public interface CommandHandlerHome extends javax.ejb.EJBHome { public CommandHandler create() throws javax.ejb.CreateException, java.rmi.RemoteException; } public class CommandHandlerBean implements SessionBean { public void ejbCreate() throws CreateException { } public void setSessionContext( SessionContext aContext ) throws EJBException {} public void ejbActivate() throws EJBException { } public void ejbPassivate() throws EJBException { } public void ejbRemove() throws EJBException { } public Command executeCommand(Command command) throws java.rmi.RemoteException { final Command param = (Command)command; try { param.execute();

125

4. Dagtk Nesneler
HibernateSession.commitTransaction(); } catch (HibernateException ex) { HibernateSession.rollbackTransaction(); throw new RemoteException("",ex); } catch (Exception ex) { HibernateSession.rollbackTransaction(); throw new RemoteException("",ex); } finally { HibernateSession.closeSession(); } return command; } }

Ne kadar basit olduunu gryoruz. CommanHandlerBean dsardan gelen g ou bir Commandi alp uzerinde execute metotunu armakla ykmldr. Eer c g u u u u g metot baaryla iletilirse Hibernate transaction commit edilecek, olmazsa rolls s back yaplacaktr. Her iki durumda da finally ile Hibernate oturumu kapatlr. Yanlz EJB artlarnda RMIa gre deiik, nemli bir nokta mevcuttur. s o gs o EJB artlarnda eer execute bir hata verir ise, catche gelen Exception s g RemoteException tipinde yeni bir Exception iine koyarak geriye atmamz c gerekmektedir. Yni RMI artlarndaki gibi, mesel bir HibernateException a s a nesnesini olduu gibi network uzerinden geri atamayz. Niye? g Bunun sebebi, EJB belirtiminin, bileenlerin arayzleri uzerine getirdii s u g snrlamalardr. EJB 2.1 belirtimine gre, aran tarafa geri atlabilecek hatao c g lar sadece RemoteException tipinde olabilirler. Bu durum mimarimiz uzerinde biraz snrlayc bir durum olabilir, fakat RemoteException iine dier bir c g Exception gmmemiz mmkn olduu iin, bize gelen HibernateException o u u g c nesnesini RemoteException iine gmerek geri gnderebiliriz (RemoteExcepc o o tion kurucu metotu parametre olarak dier bir Exception nesnesini alabilir, ve g bir kez bu ekilde yaratldktan sonra iindeki nesneyle beraber geriye -aran s c c g tarafa- tanabilir). s Bir RemoteException iinde saklanan dier Exceptiona ex.detail ars c g c g ile eriebilirsiniz. O zaman aran tarafta rnek bir catch yle olacaktr: s c g o so
try { CommandHandler handler = ... UpdateCarCommand cmd = new UpdateCarCommand(car, garageId); ... handler.executeCommand(cmd); } catch (java.rmi.RemoteException e) { if (e.detail instanceof java.rmi.RemoteException) { java.rmi.RemoteException ee = (java.rmi.RemoteException)e.detail; if (ee.detail instanceof org.hibernate.StaleObjectStateException) {

126

JMS
} }

Exceptionn iine bakarken e.detail.detail diyerek niye iki seviye aa inc s g dik? Cunk servis tarafnda bir RemoteException atld zaman EJB iletiim u g s kodlar bir Exception paketlemesi daha yaparak iki RemoteException iie cc koyulmaktadr. Bu aslnda pek istenen bir durum deildir ve EJB teknolog jisinin eksi hanesinde yazlmas gereken bir gerektir. Fakat idare edilebilir ve c her artta yaplmas gerekmedii iin fazla engelleyici bir durum tekil etmez. s g c s Ustte gsterilen Exception yakalama rneini CarsEJB/WebClient projesi o o g altnda CarUpdateAction.java dosyasnda bulabilirsiniz. EJB Command mimarisi hakknda verilen detaylar bu kadar olacak. Tm u gereken ayar dosyalar belirtmeye gerek yoktur, unk ayarlar birka isim deiiklii c u c gs g yapldktan sonra CounterStateful projesininkiyle ayndr. Bitmi tm aras u balar ve garajlar projesi zaten CarsEJB altnda bulunabilir.

4.6

JMS

JMS (Java Messaging Service), nesneler, JVMler ya da sreler arasnda asenkron u c iletiimi salayan bir Java servisidir. JMS, ncelikle bir standarttr; Bir belirs g o tim (specication) belgesi ile ortaya konmutur ve piyasadaki JMS uyumlu s yazlm paketleri bu belirtimi gerekletirip, desteklerler. JMS teknolojisinden c s bahsedilirken, yedi ana kavram srekli duyacaksnz. u Queue Topic Subscriber Publisher Sender Receiver Message Broker

4.6.1

Ana Kavramlar

Queue ve Topic Uzerine bilgi yazlan ve okunan birimlerdir. Queue ve Topicin mterileri us (gnderen ve gnderilen ular) birbirleri ile asenkron iletiime gemi olurlar, o o c s c s yni, gnderen taraf gnderme ileminden hemen dner, mesajn kar tarafta a o o s o s alnp alnmam olduuna emin olmak onun grevi deildir. Kyasla metot s g o g ars yaptmz ve bu metot geri dndu zaman biliriz ki, metot iindeki c g g o ug c 127

4. Dagtk Nesneler ilemler tamamlanmtr. Asenkron iletiimde mesajn kar tarafa gvenle ulamasn s s s s u s salamak Message Brokern grevidir. g o Topicin Queuedan olan tek fark, Queue dinleyicilerinin (listener) sadece bir tanesinin Queue uzerindeki bir mesaj okumas, Topicte ise tm okuyu u cularn (subscriber) tm mesajlar ayn anda almasdr. Bir benzetme yapmak u gerekirse, Queue telefon ise, Topic bir telsizdir. Birinin konutuunu, herkes s g duyabilir. Queueya gnderilen mesajlar, sadece ve sadece tek bir kii tarafndan o s okunabilir.

Sekil 4.4: Queue ve Topic

Sender ve Receiver Queueya mesaj gnderene gnderici (sender), Topice mesaj gnderene yaync o o o (publisher) ismi verilir. Message Broker Fiziksel anlamda queue ve topicleri iinde barndran yazlma verilen isimdir. c Ticari ya da ak yazlm paketi olarak isminden bahsedilen ey, Message Broc s kerdr. Piyasadaki rnekleri JBossMQ, ActiveMQ, SonicMQ, MQSeries ve o WebSphereMQ olarak saylabilir. Eer JMS mantki (logical) bir kavram ise g Message Broker ziksel (physical) bir kavramdr. Bu kitapta kullandmz, ve projeniz iin tavsiye ettiimiz Message Brog c g ker, JBossMQ urndr. JBoss kurumundan gelen dier yazlmlar gibi, bu u u u g yazlm da ak kaynaktr. Olduka hzl, projelerde ispatlanm ve kullanm c c s 128

JMS basit bir Broker urndr. Queue ve Topic ile alkal ayarlar zaten kullan u u u a makta olduumuz jboss-service.xml ayar dosyasndan yaplabilmektedir. g Ornek iin SimpleListenerServer projesine bakabilirsiniz. c JMS sahneye kmadan nce, revata Tibco, MQSeries gibi brokerlar ve bu c o c brokerlarn kendi arayzleri, kendi arma stilleri vard. Tibco ve MQSeries u c g hla mevcutturlar, fakat JMS sahneye ktktan sonra tm broker urnleri JMS a c u u arayzn desteklemeyi setmilerdir. Artk Tibco ve MQSeries urnleri JMS u u u c s u uzerinden kullanlabilir durumdadr.

4.6.2

JBossMQ ile Queue ve Topic Oluturmak s

Statik (duraan) Queue ya da Topic oluturmak iin, jboss-service.xml ayar g s c dosyasnda bir MBean tanm yapabiliriz. Dinamik (ilem annda) yaratlan s Queue ve Topicleri, tavsiye etmediimiz bir kullanm olduu iin, bu kitapta g g c ilemeyeceiz. s g JBoss evreninde alan her idare edilebilir nesne bir MBeandir; Statik bir c s Queue ve Topic de MBean olarak tanmlanrlar. MBean teknii sayesinde, idare g edilen nesnelerin balang deerlerini MBean teknolojisi uzerinden set etmek s c g mmkn olmaktadr. Mesela aada, kitapDemoQueue adnda bir Queuenun u u s g MBean uzerinden balatldin ve ayarlarnn yapldn gryoruz. s g g ou
<mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=kitapQueue"> <depends optional-attribute-name="DestinationManager"> jboss.mq:service=DestinationManager </depends> <attribute name="MessageCounterHistoryDayLimit">-1</attribute> </mbean>

Bir MBeanin balang deerleri <attribute name> etiketi ile set edilebilir. s c g Queue uzerindeki elerden biri olan MessageCounterHistoryDayLimit, bir og Queueya gnderilen mesajlarn saya deerinin ne kadar uzun sre muhafaza o c g u edileceini tanmlayan bir ayardr. Eksi deerler, sonsuza kadar anlamna gelir, g g art deerler verilen gn deeri kadar sayan tutulmasn salayacaktr. Bu e g u g c g og ve dier eler hakknda referans bilgisi iin, [5, sf. 238]e bavurabilirsiniz. g og c s Ustte grlen ayarlar, JBossMQda bir Queue oluturmak iin yeterlidir. ou s c Topic yaratmak iin, aadaki gibi MBean tanm yeterli olacaktr. c s g
<mbean code="org.jboss.mq.server.jmx.Topic" name="jboss.mq.destination:service=Topic,name=kitapTopic"> <depends optional-attribute-name="DestinationManager"> jboss.mq:service=DestinationManager </depends> <depends optional-attribute-name="SecurityManager"> jboss.mq:service=SecurityManager </depends> </mbean>

129

4. Dagtk Nesneler Topic MBean ayarlar iin [5, sf. 239]e bavurunuz. Ayar dosyas jboss- c s service.xmlin, gelitirme dizin yaps iinde hangi dizinde tutulduunu, ve s c g build.xml ile nasl paketlendiini grmek iin, SimpleListenerServer rnek g o c o projesine bavurabilirsiniz. s

4.6.3

Listener ile Mesaj Okumak

Statik olarak oluturduumuz Queue ve Topicden mesaj okuma tekniklerine s g bakalm. Once, listener yntemiyle okumay ileyeceiz. o s g Queue Listener Listener ynteminde bir listener, MessageListener arayznden miras alr o u u ve bir Queue uzerinde dinleyici nesne olarak set edilebilir. Bu yapldktan sonra, eer dinlenen queueya bir mesaj gelirse, o mesaj bir javax.jms.Mesg sage olarak listener nesnesinin onMessage metotuna decektir. Dinleyici nesus neler, sen beni arama, ben seni ararm mant ile ilerler. Ornek bir dinleyiciyi g s aada grmekteyiz. s g o
import import import import javax.jms.*; javax.naming.Context; java.util.Properties; javax.naming.InitialContext;

public class KitapQueueListener implements MessageListener { public KitapQueueListener() throws Exception { QueueConnectionFactory qFactory = null; InitialContext jndi = null; Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); p.put(Context.PROVIDER_URL, "jnp://localhost:1099"); // JNDI port InitialContext ctx = new InitialContext(p); QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup("ConnectionFactory"); QueueConnection qc = qcf.createQueueConnection(); Queue queue = (Queue) ctx.lookup("queue/kitapQueue"); QueueSession queueSession = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueReceiver qReceiver = queueSession.createReceiver(queue); qReceiver.setMessageListener(this); System.out.println("Listening on queue ..........");

130

JMS
qc.start(); } public void onMessage(javax.jms.Message message) { System.out.println(""+message); logger.debug(""+message); } }

Ornek kodun QueueReceiver yaratlncaya kadar olan ksm JDNI uzerinden queuenun bulunmas, queue balants ve session almas gibi basmakalp g c ilemleri iermektedir. En son aama ise listener nesnesinin, receiver uzerinde, s c s kendisini (this), setMessageListener kullanarak bir dinleyici olarak set etmesidir. Tabii bu ilem, asl dinleme ilemini balatmak iin yeterli deildir. Dins s s c g leme srecini balatmak iin, QueueConnection uzerinde start ars yaplarak u s c c g okuma ilemi ilen balatlmaldr. s s Son olarak listener kodunun kendisini tetiklemek iin, JBoss iindeki Appc c Startup ya da herhangi bir main ilevini kullanabilirsiniz. Bu ar ok basit s c g c olacaktr. Mesela komut satrndan balatlabilecek trden bir tetikleyici yle s u so olabilir:
public class QListener { public static void main(String[] args) throws Exception { KitapQueueListener k = new KitapQueueListener(); } }

SimpleListenerServer projesinin build.xmlinde yukardaki class balatabilen s qlistener adnda bir Ant taski bulacaksnz, yni, komut satrnda ant qlisa tener yazlnca yukardaki maini arlm olacak. Ilgin bir nokta: Bu tetikc g s c lemeyi yaptktan sonra, komut satrnn geri gelmediini farkedeceksiniz. Bu g bloklanmann sebebi, start ars bir dinleyici thread balatmasdr, ve bu c g s thread bitmeden, ant java komut ars geri dnmez. Bu gzel, unk test c g o u c u amal bir mainden beklediimiz de zaten budur. c g Topic Listener Queue dinleme yntemine neredeyse tpatp benzeyen topic dinleme ilemi, o s aynen queue iin olduu gibi MessageListener arayznden miras alr. c g u u
import import import import import import javax.ejb.MessageDrivenBean; javax.jms.*; javax.naming.Context; org.apache.log4j.Logger; java.util.Properties; javax.naming.InitialContext;

public class KitapTopicListener implements MessageListener {

131

4. Dagtk Nesneler

public KitapTopicListener() throws Exception { TopicConnectionFactory qFactory = null; InitialContext jndi = null; Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); p.put(Context.PROVIDER_URL, "jnp://localhost:1099"); // JNDI port InitialContext ctx = new InitialContext(p); TopicConnectionFactory qcf = (TopicConnectionFactory) ctx.lookup("ConnectionFactory"); TopicConnection qc = qcf.createTopicConnection(); Topic topic = (Topic) ctx.lookup("topic/kitapTopic"); TopicSession topicSession = qc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicSubscriber tSubscriber = topicSession.createSubscriber(topic); tSubscriber.setMessageListener(this); System.out.println("Listening on topic .........."); qc.start(); } public void onMessage(javax.jms.Message message) { System.out.println(""+message); logger.debug(""+message); } }

Not: Queue kodlamasndan topic kodlamasna geerken gzel bir c u hatrlatc kural udur: Bir queue kod ar kalbn alp, queue s c g kelimesi yerine topic, send yerine publish, receive yerine subscribe kelimesini koyarsanz, queue ilem diziniz, topic ilem dizis s sine dnm olacaktr! o us Yukardaki kodlama kalbnn queue okuma kodlamasna ok benzedii gzkyor. c g o u u Yazma ve okuma balamnda ok benzeyen queue ve topic arasndaki ana fark, g c bir mesaj okurken o mesaj ka kiinin ald ile alkaldr. Eer ustteki gibi c s g a g bir dinleyiciden birka tane olsa (deiik komut satr pencerelerinden), topice c gs bir mesaj geldiinde tm dinleyiciler bu mesaj alacaktr. g u Tetikleyici kod, queue rneine benzer olarak, alttaki gibi olacaktr: o g
public class TListener { public static void main(String[] args) throws Exception { KitapTopicListener k = new KitapTopicListener();

132

JMS
} }

Bu kod herhangi bir balang kod bloundan (mesel AppStartup iinden) s c g a c arlabilir. c g

4.6.4

Blok Eden Okuma

Listener yntemi, sen beni arama, ben seni ararm teknii ile almaktadr. o g c s JMS altyap kodlar, dinleyici uzerindeki onMessage yntemini her yeni mesaj o geldiinde armakla ykmldr, bylece ilem mant kodlarnz hibir g c g u u u u o s g c ar uzerinde blok etmemi olur. Dinleyici tekniini kullanan kodlar bu sec g s g beple asenkron olarak addedilebilir; Dinleyen taraftaki program ileyii aslnda s s kimsenin onMessage armasn beklemeden devam etmektedir. c g Fakat, baz programlarn senkron bir ekilde, yeni bir mesajn gelmesini s beklemeye ihtiyalar vardr. Bu ekildeki programlar iin, blok eden trden c s c u receive adl bir ars kullanlr. c g
eQueueReceiver qReceiver = queueSession.createReceiver(queue); qc.start(); TextMessage message = (TextMessage)qReceiver.receive();

Blok eden bu teknikle, receive ars yapld anda Java programnzn ileyii c g g s s beklemeye girer. Ta ki okunan queue uzerinde yeni bir mesaj gelinceye kadar, bu bekleyi srer, fakat yeni bir mesaj gelince, receive metotu geri dner. s u o Metot arsndan geri gelen deer, queueya (ya da topic) yeni gelen mesaj c g g nesnesi olacaktr. Yukardaki rnekte bu yeni mesaj, javax.jms.TextMessage o nesnesine cast edilmitir. s

4.6.5

Message Driven Bean Ile Okumak

Listener tekniklerinden farkl olan bir okuma ekli, Message Driven Bean (MDB) s kullanarak, queue ya da topiclerden mesaj okumaktr. MDB teknolojisi, aslnda EJB ve MessageListener tekniklerinin bir birleimidir. MDB uzerinde, aynen bir s listenerda olduu gibi, bir onMessage metotu tanmlanr, ama ayn zamanda g bir MDB bir EJBdir, unk uzerinde ejbCreate, ejbRemove gibi ilevlerin c u s tanmlanmas gerekmektedir. s Ilevsellik asndan da MDB hem EJB hem Listener gibi davranr. MDB, c aslnda bir konumsuz (stateless) EJB olduu iin bir havuzda tutulabilir. MDByi g c konrolnde iletmekte olan kap (container), dinlenen queueya gelen her mesaj u s iin havuzdan bir MDB alr, ve o MDBnin onMessage metotuna yeni gelen c mesaj aktarr. Mesaj MDB tarafndan iledikten sonra, MDB havuza geri vers ilir. MDB teknolojisinin tek dezavantaj, mesaj ltreleme tanmlarnn (ltreleme teknii detaylar iin 4.6.7 blmne baknz) sadece ayar annda (XML ile) g c ou u 133

4. Dagtk Nesneler yaplabilmesidir. Ne yazk ki, ou asenkron kurumsal uygulamann bu ayar c g deiikliine ilem annda ihtiyac vardr. gs g s Tanmlar MDB ayn zamanda bir EJB de olduu iin, derleme ve paketleme sistemi ayn g c 4.5 blmndeki EJB gibi EAR iinde SAR yntemi olacak. Hatt build.xml ou u c o a dosyalarnn her iki proje iin de ayn olduunu grebilirsiniz. c g o Her MDB iin, u dosyada ayar yaplmas gerekiyor: c c Queue ya da Topic tanm (jboss-service.xml) MDB (ejb-jar.xml) MDBnin hangi Queue ya da Topici okuduu (jboss.xml) g Liste 4.15: jboss-service.xml
<server> <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=kitapServerQueue"> <depends optional-attribute-name="DestinationManager"> jboss.mq:service=DestinationManager </depends> <attribute name="MessageCounterHistoryDayLimit">-1</attribute> </mbean> .. <!-- Log4J alakal tanmlar atland --> </server>

Liste 4.16: ejb-jar.xml


<ejb-jar > <description>KitapDemo</description> <display-name>KitapDemo</display-name> <enterprise-beans> <!-- Message Driven Beans --> <message-driven > <description></description> <ejb-name>SampleMDB</ejb-name> <ejb-class>org.mycompany.kitapdemo.mdb.SampleMDB</ejb-class> <transaction-type>Container</transaction-type> <acknowledge-mode>Auto-acknowledge</acknowledge-mode> <message-driven-destination> <destination-type>javax.jms.Queue</destination-type> </message-driven-destination> </message-driven> </enterprise-beans> </ejb-jar>

134

JMS Liste 4.17: jboss.xml


<jboss> <enterprise-beans> <message-driven> <ejb-name>SampleMDB</ejb-name> <destination-jndi-name> queue/kitapServerQueue </destination-jndi-name> </message-driven> </enterprise-beans> </jboss>

Bu ayarlara gre, SampleMDB adl MDB, kitapServerQueue adl queueya gelen o mesajlar bekleyecektir. MDBnin tanm ejb-jar.xml dosyasnda <messagedriven> etiketi altnda yaplmtr. Bu etiket altnda bir alt etiket olan <dess tination-type> etiketi altnda ise, queuemu yoksa topicmi dinlenecei belirg tilebilir. Queue tanmnn kendisi 4.6.2 blmnde anlatld gibi, jboss-serou u g vice.xml iinde yaplmtr. Queue ile MDB arasndaki balant da jboss.xml c s g uzerinde <ejb-name>i bir <destionation-jndi-name>e balamak suretiyle g gerekletirilmitir. c s s Burada tarif edilen rnek kodlar, SimpleMdbServer projesi altnda bulao bilirsiniz.

4.6.6

Mesaj Gndermek o

Bir queue ya da topice mesaj gndermek iin, ncelikle o queue ya da topic o c o nesnesini JNDI ile bulmamz gerekiyor. Daha sonra, queue balants, queue g oturumu ve en son olarak queue gndericisi yaratlarak, mesajn kendisi gndero o ilebilecektir. Aada queue mesaj gnderim tekniini gryoruz. s g o g ou
Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); p.put(Context.PROVIDER_URL, "jnp://localhost:1099"); // JNDI port 1099 InitialContext ctx = new InitialContext(p); QueueConnectionFactory qcf = (QueueConnectionFactory)ctx.lookup("ConnectionFactory"); QueueConnection qc = qcf.createQueueConnection(); Queue queue = (Queue) ctx.lookup("queue/kitapQueue"); QueueSession queueSession = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueSender queueSender = queueSession.createSender(queue); TextMessage textMessage = queueSession.createTextMessage(); textMessage.setText("merhaba dunya"); queueSender.send(textMessage);

135

4. Dagtk Nesneler Topice mesaj gnderme ilemi, queueya mesaj gndermeye olduka benzer. o s o c Hatt daha nce ortaya attmz hatrlatc kural kullanabiliriz: Queue rneindeki a o g o g queue kelimesi yerine topic, send yerine publish, receive yerine subscribe kullanrsak, alttaki rnee gelmi oluruz. o g s
// Contexti al (stteki gibi) u // .. TopicConnectionFactory qcf = (TopicConnectionFactory)ctx.lookup("ConnectionFactory"); TopicConnection qc = qcf.createTopicConnection(); Topic topic = (Topic) ctx.lookup("topic/kitapTopic"); TopicSession topicSession = qc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE); TopicPublisher topicPublisher = topicSession.createPublisher(topic); TextMessage textMessage = topicSession.createTextMessage(); textMessage.setText("merhaba dunya"); topicPublisher.publish(textMessage);

ObjectMessage Gndermek o javax.jms.TextMessage ile gnderebileceimiz mesajlar ne yazk ki snrldr. o g Kurumsal Java programlar iin, genellikle, Serializable arayznden mic u u ras alan kompleks bir Java nesnesini gndermek gerekecektir. Bu tr bir neso u neyi yollamak iin, javax.jms.TextMessage yerine javax.jms.ObjectMesc sage tipini kullanmanz gerekir. Yeni (bo) bir ObjectMessage, queueSession uzerinden createObjectMess sage ars ile yaratlr (new ile kendimiz yaratamayz). Bo bir mesaj aldktan c g s sonra, gndermek istediiniz kopmleks Java nesnesini setObject ile ObjectMeso g sage uzerinde set etmemiz gerekiyor. Gerisi, bildiimiz send arsndan ibaret g c g tir.
ComplexObject obj = ... ObjectMessage objectMessage = queueSession.createObjectMessage(); objectMessage.setObject(obj); queueSender.send(objectMessage);

Okuyan tarafta, javax.jms.Message nesnesini alnca ObjectMessagea cast etmemiz gerekir. Mesaj iindeki ComplextObjecte erimemiz iin ise, Obc s c jectMessage uzerinde getObject ars yapmamz gerekir. ObjectMessage c g uzerinde getObject arlmas, bu teknii ilk grenler iin kafa kartrc ol c g g o c s maktadr, unk elimde zaten bir object var, niye bir daha getObject aryorum c u c g duncesi ortaya kar. Burada TextMessagea bir paralel izmek gerekir; TextMesus c c sagen da uzerinde de getText ars yapmaktayz. c g 136

JMS Kalc ve Uucu Mesajlar c Bir JMS mesaj gnderirken eer hibir ek parametre tanmlamazsanz, olaan o g c g (default) olarak mesajnz kalc mesaj olarak gnderilecektir. Kalc mesaj kulo lanm, eer Message Broker kse bile, mesajlarn kaybolmasn engeller. Arka g co planda Message Broker, kalc mesajlarn kaybolmamas iin, bir veri taban ya c da dz dosyaya her mesaj yazmaktadr. Yni eer kalc mesaj gnderiyorsanz, u a g o her mesajnz bir ekilde diske yazlyor olacaktr. s Kabul edilmesi gerekir ki, her mesajn diske yazlmasnn bir performans bedeli olacaktr. Eer mesajlarnzn daha hzl gnderilmesini istiyorsanz, mesajlarnz g o uucu olarak ta gndermeniz mmkndr. Uucu mesaj gndermek iin, send c o u u u c o c arsna baz ek parametreler vermemiz gerekir. Bu ek parametre Deliveryc g Mode.NON_PERSISTENT parametresi olacaktr.
queueSender.send(textMessage, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, 0);

Dikkat: Yaplan en yaygn JMS hatalarndan biri, DeliveryMode deikenini mesaj uzerinde set etmektir. Bu arnn gnderim ilemi gs c g o s uzerinde hibir etkisi yoktur (niye hala JMS arayzlerinden depra c u cate edilmedii, ayr bir konudur). g Topic uzerinden uucu mesaj gndermek ise, queue mantna benzer ola c o g caktr.
topicPublisher.publish(textMessage, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, 0);

Kalc ve uucu mesajlar arasndaki fark grmek istiyorsak, JBossMQnun c o ve queuelarmzn alt makinaya http://host:8080/jmx-console urlinden c s g balanp, JmxConsole uygulamasn altrabiliriz. JmxConsole program, web g c s arayz uzerinden alan ve bir JBoss servisi iindeki tm MBeanleri ve u u c s c u ieriklerini listeleyebilen bir bakm programdr. Biz daha nce queue tanmlamak c o iin jboss-service.xml iinde bir queue MBeani tanmladmz iin, Jmxc c g c Consoledan bu queueyu ve ieriini grebiliriz. JmxConsole urline gidince c g o taraycnzdan queuelarn listelendii blme gidin. Sekil 4.5 bunun bir rneini g ou o g gsteriyor. o Listeden ieriini grmek istediiniz queueya tklayn (mesel kitapQueue), c g o g a ve java.util.List listMessage() yazan blme giderek Invoke dmesine ou ug tklayn. Yeni gelen sayfada queuenuzun ieriini greceksiniz. Test iin, uzerinde c g o c hibir dinleyici olmayan bir queueya kalc mesajlar yollayp JBossu kapatp c an, ve JmxConsole uzerinden mesajlar hal orada olup olmadn kontrol c a g edin. Ayn ilemi, uucu mesajlar cin de yapn. s c 137

4. Dagtk Nesneler Oncelik Metot sendin parametre listesinde grdumz parametrelerden biri, ncelik o ug u o parametresidir (priority). Bu parametre, hangi mesajn ne kadar nce hedene o ulaacan belirler. Kurumsal uygulamalarda, olaan ncelik deeri (default s g g o g priority) yeterlidir. Zamanl Mesajlar Eer bir mesaj yerine ulamadan belli bir sre sonra zamannn gemesini (exg s u c pire) istiyorsak, sende verilen son parametre olan timeToLive parametresinde bunu belirtebiliriz. Bu parametre, sadece belli bir zaman iin geerli veriler iin c c c uygun bir parametredir (mesel borsada bir hissenin anlk deeri gibi -en son a g deer 10 saniye sonra geersiz olmasn istiyorsak, vs-). Eer timeToLive iin g c g c 0 verilmi ise, mesaj zamana bal geersiz olmayacaktr. s g c

4.6.7

Filtrelemek

Bir queue ya da topice gnderilen mesajlarn iinden sadece ilgilendiimiz ve o c g bir kstasa uyan bazlarn semek istiyorsak, message selector uzerinden lc treleme tekniinin kullanmamz gerekmektedir. g Filtreleme yapmak iin, JMS mesajnda bulunan, uzerinden ltre yapac bileceimiz bir parametre gerekmektedir. Bu parametreye mesaj parametresi g ismi veriyoruz. Mesaj parametresi set etmek iin belli baz JMS arayzleri c u vardr. Her tip iin, deiik bir parametre set ars yapmak gerekiyor, tm c gs c g u listeyi altta veriyoruz.
public void setStringProperty(String name, String value);

c g Sekil 4.5: JmxConsoledan Queue Ieriini Grmek o 138

JMS
public public public public public public public public void void void void void void void void setIntProperty(String name, int value); setBooleanProperty(String name, boolean value); setDoubleProperty(String name, double value); setFloatProperty(String name, float value); setByteProperty(String name, byte value); setLongProperty(String name, long value); setShortProperty(String name, short value); setObjectProperty(String name, Object value);

O zaman, gnderen taraf bir mesaj parametresi set etmek isterse, u ekilde o s s deitirilmesi gerekecektir. gs
ComplexObject obj = ... ObjectMessage objectMessage = queueSession.createObjectMessage(); objectMessage.setObject(obj); objectMessage.setStringProperty("param1", 123456789); queueSender.send(objectMessage);

Burada, dier gnderme ilemlerine ek olarak, setStringProperty ile String g o s tipinde bir mesaj parametresi set ettik. Artk param1 uzerinden alacak bir c s lre yaratabiliriz. Filtreleri, hem listener hem de receive teknikleri uzerinden kullanmak mmkndr. Her art iin ltre yaratmay altta grelim. u u u s c o Listener ve Filtre Mesel setStringProperty ile set edilen, param1 adl parametre uzerinden a ileyen, ve queue uzerinde bekleyen bir listener uzerinden ltre oluturmak iin s s c
QueueReceiver qReceiver; qReceiver = queueSession.createReceiver(queue, param1 = 123456789);

Ayn ekilde, ama bu sefer topic uzerinde beklemek iin, s c


TopicSubscriber tSubscriber; tSubscriber = topicSession.createSubscriber(topic, param1 = 123456789, false);

Bu arlar yapldktan sonra, onMessagee gelen nesneler, artk sadece ve c g sadece ltre artlarna uyan javax.jms.Message nesneleri olacaktr. s Receive ve Filtre Bir queue uzerinden, blok eden receive uzerinden ltre ile mesaj almak iin, c unlar yapmak gerekir: s
QueueReceiver qReceiver; qReceiver = queueSession.createReceiver(queue, param1 = 123456789);

139

4. Dagtk Nesneler
qc.start(); javax.jms.Message message = qReceiver.receive();

Topic iin c
TopicSubscriber tSubscriber; tSubscriber = topicSession.createSubscriber(topic, param1 = 123456789, false); qc.start(); javax.jms.Message message = tSubscriber.receive();

Yni, bir receiver ya da subscriber yaratmak, dinleyici kodlamas ile neredeyse a ayndr, iki fark ile: Blok eden yntemde setMessageListener ile dinleyici set o edilmez, ikincisi, mesaj alma ilemi receive metotu arlarak, receiver/subs c g scriber referans uzerinden direk olarak yaplr.

4.7

JMS ve Command Mimarisi

Uzaktan Metot Cars yntemleri olan RMI ve EJB teknolojileri ile, Command g o mimarimizin ne kadar rahat gerekletirilebildiini grdk. Command nesneleri c s g o u Serializable nesneler olduklar iin network uzerinden rahatlkla gnderc o ilebiliyor, ve ulatklar noktada CommandHandler tarafndan iletilebiliyordu. s s Eer bu mimariyi asenkron bir yapya evirmek istersek, queue kavramn g c Command mimarimize bir ekilde dahil etmemiz gerekecek. Tahmin edilebilecei s g uzere, daha nce bir execute metot arsna parametre olan Commandler, o c g artk queuelar uzerinden gidip gelen nesneler olacaklar. Command ileyen CommandHandler ise, artk bir RMI ya da EJB ness nesi deil, bir JMS dinleyicisi olacaktr. Bu kavram deiikliini iyice belirg gs g ginletirmek iin, ileyici nesnenin ismini CommandListener olarak deitireceiz. s c s gs g

4.7.1

Fiziksel Yap

JMS bazl mimarilerde gndeme gelen ilk sorulardan biri, ka tane queue kulu c lanalm sorusudur. Bizce bu soruya cevap, basitlik, ksalk ve bakm rahatl g balamnda mmkn olabildiince az olmaldr. Nasl olsa bir queueya birden g u u g fazla gnderici mesaj gnderebilir ve bir queuedan birden fazla okuyucu mesaj o o okuyabilecei iin, queue saysnda yaplan bir azaltma programn doru ileyii g c g s s asndan bir yan etkiye sebebiyet vermez. Sekil 4.6 uzerinde ift queue ile kuc c rulmu bir Command yaps gryoruz. s ou Bu yapda, istekleri gndermek iin bir queue, cevaplarn geri gnderilmesi o c o iin baka bir queue ayrlmtr. CommandListener, istek queuesu uzerinden c s s dinleyici olarak set edilmitir, ve bu queueya yazlan her Commandi annda s alp, uzerinde execute ilemini aracak ve cevab (yni ayn Commandi) ik s c g a inci queueya yazacaktr. Web tarafndaki JVM birden fazla kullancy idare 140

JMS VE COMMAND MIMARISI edebilecei iin herhangi bir anda, ezamanl birok kullancnn istek Comg c s c mandleri istek queuesu uzerinde dizilmi olur. CommandListener bu istekleri s teker teker, o queueda olan srasyla iler. s Bu yapya alternatif olarak, mesel, her mesaj gnderilirken bir geici queue a o c yaratmak, bu cevap queuesunu JMS mesajnn iine cevab buraya yaz babnda c eklemek, ve cevab o geici queueya almak dunlebilir. Fakat bu seenein c us u c g performans olarak kt yan etkileri olacaktr: Her mesaj iin yeni queue yaratp ou c yoketmek, sistemin btnn yavalatr. uu u u s Cift queue mimarisinin dier bir faydal taraf, sistemin ne kadar ykl olduunu g u u g sadece iki queueda ka tane mesaj birikmi olduuna bakarak anlayabilecek olc s g mamzdr. Eer queuelarda, zellikle cevap queuesunda fazla mesaj birikmi g o s ise, CommandListener tarafnn yk kaldramadn anlar, ve birden fazla u u g ileyici JVM devreye sokabiliriz. Bunun iin hibir ekstra ayarlama yapmamz s c c gerekmeyecektir. Ayn queue uzerindeki her okuyucu bir mesaj okurken, dierlerinin g nne gemez. JMS okuyucu kurallarna gre bir mesaj alan onu kapm o u c o s addedilir, ve o mesajn ileyicisi o olur. Bu JMS zellii, yk datm asnda s o g u g c biilmi kaftandr. c s

4.7.2

Kullanclar Ayrt Etmek

Sekil 4.6 ve 4.7 uzerinde grdumz yapya bir daha bakalm: Eer hibir o ug u g c ek ilem yapmazsak, bu mimari alacak mdr? Hayr, yapmamz gereken bir s c s

Web

Server

CommandListener (1) Yaz (2) Oku

(4) Oku

(3) Yaz

Sekil 4.6: JMS Uzerinden Command Mimarisi 141

4. Dagtk Nesneler ek ilem daha kald: Web tarafna gelen cevap mesajlarn, sadece ve sadece s o istei gndermi olan kullancya gndermek. Eer bunu yapmazsak, birok g o s o g c kullancy idare etmek iin yazlm Web taraf, birok kullancnn mesajn c s c ayn queueya koyacak, ve birok kullancnn cevaplarn baka bir queueda c s s birikmi ve kark olarak almaya alacaktr. Ilem doruluu olarak bu probs s c s g g lemlere yolaacaktr. c Peki her kullancya sadece ilgilendii mesajlar nasl verebiliriz? 4.6.7 blmnde g ou u ilediimiz ltreleme tekniini hatrlayn: Eer her kullancya zel bir kims g g g o lik nosu bulabilirsek, bu kimlik deerini her mesaj uzerine mesaj parameg tresi olarak set edebiliriz, ve CommandListener geri gelecek cevap uzerine ayn parametreyi tekrar koyar. Web tarafndaki dinleyiciye de, bu mesaj parametresi uzerinden ltreleme yaparsa, bylece her kullancnn sadece kendisi iin o c olan cevap mesajlarn almasn salam oluruz. g s Web mimarisinde, her kullancya zel bir kimlik bulmak ok basittir. Bu o c kimlik, sessionId deikeninden bakas deildir. Bir Struts Action iinde sesgs s g c sionIdyi almak iin request.getSession().getId() arsn yapmak, ve c c g mesaj uzerine bu kimlii setStringProperty ars ile koymak yeterli ola g c g caktr. Eer aran taraf bir zengin kullanc ise (mesel Swing), o zaman her g c g a balanan kullancnn ayr bir JVMi var demektir. Byle bir yapda Mesg o sage Broker da ayr ve tek bir JVM iinde alyor olacaktr. O zaman mesaj c c s ayrtrma problemini yle zeriz: Zengin nyz ortamnda sessionId yoks so co o u tur, ama her kullanc iin bir rasgele kimlik ureterek mesaj uzerinde set etmek c ok kolaydr. Rasgele kimlik uretmek iin c c

Web

Server

CommandListener (1) Yaz (2) Oku

(4) Oku

(3) Yaz

c Sekil 4.7: JMS Bazl Mimariyi Oleklemek 142

JMS VE COMMAND MIMARISI


java.util.Random generator = new java.util.Random(); int id = generator.nextInt(1000); // 1000den kk idler ret ucu u

ars kullanlabilir. c g

4.7.3

Kodlar

JMS uzerinden Command mimarisinin kodlarna gelelim (bu kodlarn tamam lanm hlini, CarJMS projesi iinde bulabilirsiniz). s a c o Ilk nce iki queueyu tanmlayalm. Istek Commandlerinin konduu queue g ismi, kitapWebQueue, cevap Commandlerinin okunduu queue ise kitapServerQueue g olsun. Queue Tanmlar Liste 4.18: jboss-service.xml
<server> ... <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=kitapServerQueue"> <depends optional-attribute-name="DestinationManager"> jboss.mq:service=DestinationManager </depends> <attribute name="MessageCounterHistoryDayLimit">-1</attribute> </mbean> <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=kitapWebQueue"> <depends optional-attribute-name="DestinationManager"> jboss.mq:service=DestinationManager </depends> <attribute name="MessageCounterHistoryDayLimit">-1</attribute> </mbean> </server>

Bu queuelar Web tarafnda tanmladk (yni ustteki jboss-service.xml dosyas a CarsJMS/WebClient altnda), unk, yk datm amal birden fazla ileyici c u u g c s (dinleyici) JVM balatrsak, yeni dinleyicilerin (ileyicilerin) ayn queuelara, s s yni ayn JVMe gitmesi lazmdr. Eer queuelar servis tarafnda olsa idi, her a g balatlan ileyici JVM, yeni queuelar balatm olurdu ve bu uygun olmazd. s s s s Alternatif ziksel yap olarak, ayr bir JVM balatarak Message Broker bu s ayr JVMde tutmay seebilirsiniz. Biz basitlik ve idare edilebilirlik asndan c c queuelar Web tarafna koymay setik. Sekil 4.8 uzerinde bu alternatif ziksel c yapy gryorsunuz. ou 143

4. Dagtk Nesneler Balant, Oturum, Gnderici g o Commandleri gndermekle ykml Web tarafnda, gnderilen ve okunan iki o u u u o queue iin birer JMS balants, JMS oturumu, JMS gnderici ve JMS okuyuc g o cusu yaratmamz gerekiyor. Her kullanc iin bu ilemi bir kez yapmamz c s yeterli, yni her mesaj iin bu ilemlerin tekrar tekrar yaplmasna gerek yok. a c s Bu sebeple, gereken JMS referanslarn bir kez yaratp, her kullancya ait web oturumu uzerinde deikenler olarak tutabiliriz. Bylece, gerekince bu nes gs o nelere erimek ok hzl olacaktr. JMS referanslarna ilk ihtiya duyulduu s c c g anda otomatik olarak yaratabilecek ServiceReferencesFilter adnda bir ltre iinde bu ilemleri yapabiliriz. c s
public class ServiceReferencesFilter implements Filter { private Logger logger = Logger.getLogger("appLogger"); public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession();

Web

Server

Message Broker (1) Yaz (2) Oku (4) Oku CommandListener

(3) Yaz

Sekil 4.8: Message Broker Ayr JVM Uzerinde 144

JMS VE COMMAND MIMARISI

try { if (session.getAttribute("senderSession") == null || session.getAttribute("sender") == null) { QueueConnectionFactory qFactory = null; // ... // Contexti al // .. QueueConnectionFactory qcf = (QueueConnectionFactory)ctx.lookup("ConnectionFactory"); QueueConnection qc = qcf.createQueueConnection(); Queue queueServer = (Queue) ctx.lookup("queue/kitapServerQueue"); QueueSession queueSession = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueSender sender = queueSession.createSender(queueServer); session.setAttribute("sender", sender); session.setAttribute("senderSession", queueSession); session.setAttribute("senderQueueConnection", qc); logger.info("Sender and Session Created"); }

if (session.getAttribute("receiverSession") == null || session.getAttribute("receiver") == null) { // ... // Contexti al // .. QueueConnectionFactory qcf = (QueueConnectionFactory)ctx.lookup("ConnectionFactory"); QueueConnection qc = qcf.createQueueConnection(); Queue queue = (Queue) ctx.lookup("queue/kitapWebQueue"); QueueSession queueSession = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); String filter = "sessionId = " + ((HttpServletRequest)request).getSession().getId() + ""; QueueReceiver receiver = queueSession.createReceiver(queue, filter);

145

4. Dagtk Nesneler
session.setAttribute("receiverSession", queueSession); session.setAttribute("receiver", receiver); session.setAttribute("receiverQueueConnection", qc); } } catch (Exception e) { e.printStackTrace(); logger.error("",e); } // end of try-catch chain.doFilter(request, response); } public void destroy() { } }

Her kullancnn mesajlarn ayrtedebilmek iin ltre kullanacamzdan bahc g setmitik. Okuyucu nesneyi yaratrken, bu ltreyi de yukarda yaratm olduumuzu s s g gryorsunuz. ou JmsHelper Web tarafnda iimiz neredeyse bitti. Struts Actionlar iinde Command yaratp s c queue uzerine koymak ve cevab okuma ilemlerinin kodlamasn kolaylatrmak s s iin, bir yardmc metot yazmaktan baka bir i kalmad. Bu metotu,JmsHelper c s s adnda bir nesne iine koyalm, ve ary static olarak tanmlayalm. Bu c c g yardmc arya sendCommand ismi verilecek, ve parametre olarak bir command c g alp, geriye cevap Commandini geri getirmekten baka bir grevi olmayacak. s o
public class JmsHelper { private static Logger logger = Logger.getLogger("appLogger"); public JmsHelper() { } public static Command sendCommand(HttpServletRequest request, Command command) { Command resCmd = null; try { HttpSession session = ((HttpServletRequest) request).getSession(); QueueSender queueSender = (QueueSender)session.getAttribute("sender"); QueueSession queueSession = (QueueSession)session.getAttribute("senderSession"); QueueReceiver queueReceiver = (QueueReceiver)session.getAttribute("receiver");

146

JMS VE COMMAND MIMARISI


QueueSession receiverSession = (QueueSession)session.getAttribute("receiverSession"); QueueConnection receiverQueueConnection = (QueueConnection)session.getAttribute("receiverQueueConnection"); ObjectMessage objectMessage = queueSession.createObjectMessage(); objectMessage.setObject(command); objectMessage.setStringProperty("sessionId", request.getSession().getId()); queueSender.send(objectMessage, DeliveryMode.NON_PERSISTENT, 4, 0); receiverQueueConnection.start(); ObjectMessage resObj = (ObjectMessage)queueReceiver.receive(); resCmd = (Command)resObj.getObject(); } catch (Exception e) { logger.error("",e); } // end of try-catch return resCmd; } }

Yardmc metotun ieriine bakarsak, parametreden olarak gelen Command c g nesnesinin setObject ile bir ObjectMessage uzerinde set edildiini gryoruz. g ou Daha sonra JMS send ile Command gnderilmekte, ve hemen arkasndan cevap o senkron olarak receive ars uzerinden beklenmektedir. Gnderilen mesaj c g o uzerine bir sessionId parametresi konulmasn tabii ki unutmadk, ve zaten okuyucu nesnemizde ayn sessionId uzerinden ltreleyecek ekilde yazlmt. s s Hatalar JMS Command mimarisi mesaj gnderen ve gnderilen taraar birbirinden o o koparp asenkron hline getirdii iin, servis tarafnda exception atldi zaman a g c g bu hatann bir ekilde mesaj gnderen tarafna aktarlmas gerekir. Bu aktarm, s o EJB ya da RMI rneinde olduu gibi metot arsnn bir paras olamaz, o g g c g c unk JMS Command mimarisinde metot ars yoktur. O zaman bir hatay c u c g nasl bildireceiz? g Exception Command nesnesinin iine gmebiliriz. Command ust snfndan c o miras alan bir ExceptionCommand snf yazarz, ve tm Command classlar u Command yerine ExceptionCommand snfndan miras alr.
public abstract class ExceptionCommand implements Command { Throwable exception;

147

4. Dagtk Nesneler
public Throwable getException() { return exception; } public void setException(Throwable newException) { this.exception = newException; } } public class AddCarCommand extends ExceptionCommand { .. }

ExceptionCommand uzerinde bir Throwable referans olduunu gryoruz (her g ou Exception ayn zamanda bir Throwable tipidir). Artk servis tarafnda bir hata alnd zaman, CommandListener bu hatay cevap Commandi iine gmerek g c o cevap queuesuna yazarak gnderen tarafa geri verebilecektir. o Balanan taraf eer bir hatann varln kontrol etmek istiyorsa, cevap g g g queuesundan ald Command nesnesinin iine getException ile bakarak, hata g c tipini instanceof ile kontrol eder, ve try catch mantnn bir benzerini g gerekletirebilir. c s
UpdateCarCommand cmd = new UpdateCarCommand(car, garageId); UpdateCarCommand resCmd = (UpdateCarCommand)JmsHelper.sendCommand(request, cmd); if (resCmd.getException() instanceof org.hibernate.StaleObjectStateException) { String id = (String)daf.get("licensePlate");

Sekil 4.9: Hata Tayc Command s 148

JMS VE COMMAND MIMARISI


... }

CommandListener CommandListener bir JMS dinleyicisi ve Command ileyicisidir. Istek queuesu s (kitapWebQueue) uzerine gelen her mesaj CommandListenern onMessage meto tuna der. Bu mesaj iinde bir Command nesnesi olacaktr. Bu nesne alndktan us c sonra, uzerinde execute arlr. Eer bir hata olmu ise, exception yakala c g g s narak commandin uzerine yazlr. Cevap iin yeni bir ObjectMessage oluturulur, c s ama istek iin gelen ayn Command, cevap olarak ObjectMessage uzerinde c konur. Bu Command, cevap queuesu uzerinden send ile gnderilir. o Bitmi kodlar, CarJMS/Server projesi altnda bulabilirsiniz. s Liste 4.19: CommandListener.java
public class CommandListener implements MessageListener { private Logger logger = Logger.getLogger("appLogger"); QueueSender sender = null; QueueSession queueSessionS = null; Queue queueS = null;; public CommandListener() throws Exception { QueueConnectionFactory qFactory = null; // ... // Contexti al // .. QueueConnectionFactory qcf = (QueueConnectionFactory)ctx.lookup("ConnectionFactory"); QueueConnection qc = qcf.createQueueConnection(); Queue queue = (Queue) ctx.lookup("queue/kitapServerQueue"); QueueSession queueSession = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); QueueReceiver qReceiver = queueSession.createReceiver(queue); qReceiver.setMessageListener(this); System.out.println("Listening on command queue .........."); qc.start(); // bir de cevaplarn yazlaca queueya session a g c queueS = (Queue) ctx.lookup("queue/kitapWebQueue"); queueSessionS = qc.createQueueSession(false,

149

4. Dagtk Nesneler
Session.AUTO_ACKNOWLEDGE); this.sender = queueSessionS.createSender(queueS); System.out.println("Ready to send .........."); } public void onMessage(javax.jms.Message message) { ExceptionCommand command = null; ObjectMessage sendObjectMessage = null; try { ObjectMessage objectMessage = (ObjectMessage)message; command = (ExceptionCommand) objectMessage.getObject(); sendObjectMessage = queueSessionS.createObjectMessage(); sendObjectMessage.setStringProperty ("sessionId", message.getStringProperty("sessionId")); command.execute(); HibernateSession.commitTransaction(); } catch (HibernateException ex) { HibernateSession.rollbackTransaction(); if (logger.isDebugEnabled()) logger.debug("rolled back"); command.setException(ex); logger.error("hibernate exception",ex); } catch (Exception ex) { HibernateSession.rollbackTransaction(); command.setException(ex); logger.error("exception",ex); } finally { HibernateSession.closeSession(); if (logger.isDebugEnabled()) logger.debug("session closed"); } try { // commandi mesaj zerine koy u sendObjectMessage.setObject(command); // cevap queuesu zerinden geriye yolla u sender.send(sendObjectMessage, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, 0); } catch (JMSException ex) { logger.error("",ex); } } }

150

Bl m 5 ou

c Performans, Oleklemek

Bu Bl mdekiler ou Yk testleri ve JMeter u Bir uygulamann tkanma noktalarn bulmak Performans iyiletirmeleri s ceklemek Ol

151

5. Performans, Olceklemek uzel ileyen bir uygulamay tanmlamak iin, o programn hatasz s c almas artk yeterli bir kstas olmamaktadr. Gnmzde doru ama c s u u u g yava alan bir sistem kullanclarn soutaca iin, aynen yanl s c s g g c s alan bir sistem gibi istenmeyen bir sonu urndr. c s c u u u Tarihsel olarak kurumsal programclk (IT) dnyasnda uzun sredir birikmi u u s bir yazlm ihtiyac (application backlog) durumu mevcut idi. Bu durum, programclarn acele yazdklar sistemlerini sadece doruluk asndan test edg c erek, performans konularn sonraya brakmalarna sebebiyet vermitir. Fakat s mteri ile direk iletiimde olan ve birebir satma amal olan e-ticaret sistemus s c lerinin yaygnlamas ile bir paradigma deiiklii meydana geldi. Artk bir Web s gs g sistemi mterisini yava bir sistem ile bekletmek istemeyecekti, unk rakibi us s c u bir tklama mesafesi kadar yakndayd. Bylece gnmzdeki hem doruluk o u u u g hem performans amac gden senteze gelmi oluyoruz. Yeni yaklama gre peru s s o formans analizi/iyiletirmesi, sadece sonda yaplan, ve gerektii anda yemek s g tari gibi bir araya konan baz ufak numaralar toplam olmamaldr. Performans konusu, aynen bakm rahat kod yazmak iin yazlm mhendislii c u g emsiyesinin altlnda oluturulduu gibi, bir yntem, bir sre ve dun ekli s s g o u c us us s hline gelmelidir. a

5.1

Kavramlar

Bir sistemin performans durumu ve gereklilikleri hakknda konuurken be ok s sc basit ana kavram kullanmak yeterlidir [7, sf. 42]. Bunlar: Yk (workload) u Cevap zaman (response time) Uretilen i (throughput) s Kaynak kullanm (resource utilization) Kaynak servisleme zaman (resource service times) Hesap kaynaklarndan (computing resources) oluan bir bilgisayar sistemi, bir s y k uzerinde almaya balad zaman dardan grlebilen lumler cevap u c s s g s ou o c zaman ve uretilen i olacaktr, ve bu luler sistemin da dnk performans s o c s o u lutleridir. Sistemin i performansn trif eden lumler kaynak kullanm o c c a o c ve kaynak servis zaman, dardan grlen performansa bir teknik aklama s ou c salarlar. g Cevap zaman en basit hliyle, tek bir ii yapmak iin harcanan zaa s c mandr. Her i tipinin deiik cevap zamanlar olabilir. Uretilen i ise bir s gs s sistemin toplam, ya da ilem bl zaman (say/saniye -rate-) olarak ne kadar s ou i yaptnn gstergesidir. Cevap zaman ve yaplan i lumleri bir sistem s g o s o c uzerindeki yk ile dorudan balantldr. Belli bir krlma noktasndan sonra u g g 152

Kavramlar sistemimiz ok fazla yk kaldrmayp, cevap zaman ve uretilen i lumlerinde c u u s o c du yaayabilir. Ya da, belli bir cevap zamann kaldrmak iin yazlm bir uss s c s sistem, uzerindeki yk arttka uretilen i lumnde art grp, cevap za u c s o c u s ou mannda hi art grmeyebilir (bu, performans iyi olan bir sisteme rnektir). c s o o Yni cevap zaman ve uretilen i lumleri her zaman bir yk erevesi (cona s o c u c c text) iinde telfuz edilmelidir. c a Kaynaklar arasnda mikroilemci (CPU), sabit diskler (hard drive), bellek s (memory) ve a (network) balants saylabilir. g g Mikroilemci sistemimizin en hzl birimidir ve bir bilgisayarn kalbidir. s Her trl veri alsverii (I/O), program iletme ve hesap yapma gibi hayati u u s s ileri halleder. Bu ekilde bir hayati grevi olmas sebebiyle, genellikle yava s s o s ileyen sistemlerde ilk sulanan birim mikroilemci olur. Fakat bir nal anals c s ize atlamadan nce, tm faktrlere bakmamz gerekir: Belki mikroilemci ok o u o s c fazla ama ayn trden ilemi ayn anda ilemeye mecbur braklmtr, yni u s s s a mikroilemci zaman iin bir yar szkonusudur. Ya da, mikroilemci veri s c s o s alverii ile de sorumlu olduu iin ve kurumsal sistemler genellikle IO baml s s g c g (IO bound) olduklar iin, belki de mikroilemci bir IO aracnn boalmasn c s s bekliyor ve genellikle bo (idle) duruyor olabilir. Bu yzden, mikroilemci temelli s u s olduunu sandmz bu problemi zmek iin yeni bir mikroilemci eklersek, g g co c s sorunumuzu zlmeyecektir. Bu sefer yeni mikroilemci de bo beklemeye co u s s balayacaktr. s Bellek CPUnun hatrlamak istedii verileri, ilemek istedii ilemleri (ing s g s structions) tuttuu bir depodur. Uucu bellek (RAM) kalc bellekten (disk) g c her zaman daha hzldr fakat bellek, dier tm kaynaklar gibi, snrldr. Eer g u g uygulamamz elde mevcut olandan fazla bellek istiyorsa, modern iletim siss temleri disk sistemini bellek gibi kullanabilme, sayfalama (paging) yeteneine g sahiptir. Fakat uygulamamzn ok fazla sayfalama yapmaya balamas da istec s nilen bir ey deildir, unk ok hzl olduunu bildiimiz bellek iin yazdmz s g c u c g g c g kodlar, artk diske giderek daha yava bir ortamda almaya balamtr. Her s c s s s modern iletim sistemi, yapt sayfalama istatistiklerini paylama yeteneine s g s g sahiptir. Bu istatistikleri kullanarak, eer ok yksek sayfalama grrsek, o g c u ou zaman uucu bellein gereinden fazla kullanm (utilized) grdun anlayac g g o ug u biliriz. Czm ya bellek eklemek, ya bellek kullanmn azaltmaktr (yk yeni o u u u makinalara aktararak, ya da kodu deitirerek). gs Diskler, kalc olmasn istediimiz iletiimin (IO) hededir. Bir disk, manyetik g s disklerden oluur (ismi de buradan gelir) ve program kmesi, elektrik kesins co tisi gibi kazasal durumlarda bilgimizi koruyacak olan ortam olma grevini yao par. Kaybolmasn istemediimiz verilerin diskte tutulmas, bu yzden prog u gram doruluu asndan byk nem tar. Birden fazla diski birarada kulg g c u u o s lanmak istiyorsanz, RAID ad verilen disk yntemi ihtiyacnz karlyabilir. o s RAID, Redundant Array of Inexpensive Disks (Gereinden Fazla Alnm g s Ucuz Disk Kmesi) ksaltmasndan gelir, ve depolanmak istenen veriyi birden u fazla paraya blerek (striping), bu paralar her ucuz disk uzerinde para para c o c c c tutarak veriye eriimi hzlandrmay amalar. RAID bir nbellek (cache) ile kuls c o 153

5. Performans, Olceklemek lanrsa daha ideal bir ortam hline gelir, unk nbelleksiz olarak kullanmda a c u o ufak ve noktasal eriimlerin (random access) srekli tm disklere giderek paralel s u u ilemenin avantajlarn yoketmesi mmkndr. Bu sebeple RAID zmn aldnz s u u u co u u u g rmann teknik altyapsn iyi tanmanz gerekmektedir. Byk miktardaki veri transferleri doal olarak birka diske dalacandan, u u g c g g bu tr kullanm iin RAIDin faydas olacaktr. u c A birden fazla bilgisayarn birbiri ile haberlemesi iin gereken altyapdr, g s c ve Internet + servis tarafnda bir kme mimarisi durumunda performans etku ileyecek nemli faktrlerden biridir. A servisleme zaman uzerinde, ada kulo o g g lanlan iletiim protokolnn (TCP/IP, UDP) byk etkileri vardr, bu sebeple s u u u u mimari tasarmmzda bilinmesi gereken nemli bir faktrdr. o o u

5.2

Yaklam s

Iyi perform eden bir sistemin performans kriteri, her zaman mteriye bal us g olan bir detaydr. Bu yzden projeye balamadan nce, sistem hakknda isu s o tenilen performans lulerinin mteriden alnmas gerekecektir. Bu lulerin o c us o c alnmasn aynen uygulamann zellik listesini aldmz ciddiyette almalyz o g unk aynen bir programn doruluunu zellik listesinin ne olduu belirledii c u g g o g g gibi, ne kadar hzl olduunu da yine mterinin belirttii performans kriterleri g us g belirleyecektir. Iyi perform eden bir sistemin teknik gerekletirimi iin, dunce eklimizin c s c us s iyi performans kavram uzerine kurulmasndan bahsettik. O zaman, byle bir o sistemi yazarken dikkat etmemiz gereken kurallar ve aklmzda tutmamz gereken prensipleri sralayalm: Bu kurallar ve prensipler, daha ilk kodu yazdmz ang dan itibaren dikkat edilecek kurallardr. Veri tabanna ne zaman gidersek, orada yaplan ilemi (transaction) ufak s tutmalyz. Veri tabanlar kmeler ile alsmay severler. Ornek olarak 100 tane SQL u c UPDATE yapan sorgular yerine, 100 satr tek bir SQL ile gncelleyen bir u sorgu veri tabanlar tarafndan daha abuk iletilir. c s Mimarimizdeki ziksel katmanlar, gereinden fazla olmamaldr. Networke g her kmzda belli bir performans bedeli dyoruz. c s o u Sk eriilen ve az deien birimler, nbellee konmaldr (bir veri nesnesi, s gs o g veri taban balants gibi). g Kod bakm asndan ok kullancl sistemler, tek bir makina iin yazlyormu c c c s c gibi yazlabilmelidir. Olekleme, uygulama servis paketinin ayarlarn deitirmek gs c suretiyle yaplan, programlama d bir ilem olmaldr. Olekleme zaman s s gelince, ek bir makina (donanm) koyarak sistemin ilem gcn arttrabilmeliyiz. s u u u Bu durum, kattan insan zinciri (Sekil 5.1) yapmaya benzer. g 154

Yaklam s Tm bunlara ramen, eer uygulamamzn yava ilediini gzlemliyorsak, u g g s s g o o zaman detayl analiz yapma zamanmz gelmitir. s

5.2.1

Analiz

Cevap zaman ve uretilen i luleri her zaman bir yk erevesinde anlaml s o c u c c olduu iin, programmzn performansn analiz etmek iin yapay bir yk g c c u yaratmalyz. Bu tr bir teste yk testi ad verilmektedir. Yk testi, tek ya u u u da daha fazla makinann yzlerce hatt binlerce kullancy taklit (simle) u a u etmesi ile servis tarafndaki kodlarnz uzerinde bir kullanc trai yaratmas, g ve bizim de bu reaksiyonlar ve performans lutlerini toplamamza verilen o c isimdir. Apache JMeter bu tr bir taklit yk oluturacak aralardan biridir, u u u s c bu urn 5.3.1 blmnde daha yakndan tanyacaz. u u ou u g Yk testine balamadan nce, aklmzda, projenin banda aldmz bekleu s o s g nen performans lulerinin olmaldr. Cunk yk testinin sonularn topladktan o c u u c sonra, iimizin bitip bitmediini belli edecek luler bunlar olacaktr. Bu beks g o c lenen luler projenin banda mteri tarafnda belirtilmi luler olacaktr. o c s us s o c Mesel, sistemin xx kadar ezamanl aktif kullancya hizmet verebilmesini isa s tiyorum, ve her sayfann cevap zaman (response time) yy saniye altnda olmal gibi. Yk testi srasnda aynen sonu ortamnda (production) kullanlaca miku c g tarda test verisi kullanmak ok nemlidir. Veri miktar ve eidi her zaman c o c s gerek sonu ortamn yanstacak ekilde olmaldr. Ayn ekilde test donanm c c s s ortam da, sonu ortamn mmknse bire bir, deilse ok yakn bir ekilde c u u g c s yanstmaldr. Artk tkanma noktalarn bulmaya balayabiliriz. Tkanma noktalar, uygus lamamzn bir yerinde kaynaklar uzerinde unlardan birinin gstergesidir: s o Kaynak kullanm fazlal (high utilization) g Kaynaa eriim yar (fazlall) srasnda kaynan boulmas g s s g g g O zaman, uygulamamz ilerken ilk nce kaynaklar takip edip, kullanm dus o rumu ve bekleme zamanlarn takip etmeliyiz. Her kaynan kendine has bir g takip arac vardr. CPU iin vmstat, disk iin vmstat ve iostat gibi. c c

Sekil 5.1: Tek Makina Gibi Yaz, Otomatik Coalt g 155

5. Performans, Olceklemek Iyi ileyen bir sistemi (uygulama art iletim sistemi) analiz etmek iin, s s c u ekilde bir irdeleme yapabiliriz: Sistem optimal sayda kullancnn isteks s lerini optimal bir hzda karlyor iken, mikroilemci kullanm %90 uzerinde s s olmaldr. Bu, ilemcinin megul olduunu gsterir ve bu iyiye bir iarettir. s s g o s Demek ki uygulamamz, sistemin mmkn olan tm gcn kullanmaktadr. u u u u u u Bu durumun tersi de olabilir: CPU kullanm %100de, fakat desteklenebilen kullanc says bekleneden az ise, demek ki uygulamamzn baz blmleri ou gereksiz bir ekilde CPU zaman yemektedir. Hangi kod parasnn bu zaman s c yediini anlamak iin Proler ve benzeri aralarla daha detayl analize devam g c c etmeliyiz. Peki, ne kadar ezamanl kullanc/ilem iin ne kadar bellek kullanmak s s c gerekir? Bunun cevabn Kurumsal Webin Altn Kanunu veriyor. Simdiye kadar kurduumuz Kurumsal Web uygulamalarnn ileyiine ve kapasitesine g s s bakarak gelitirdiimiz bu oran, yledir: s g so

1 Ghz hzndaki mikroilemci uzerinde, 1 GB JVM bellei ile alan s g c s uygulamamz, ayn anda 500 oturumu (session) idare edebilir.

Bu ayarlar yaptysak ama sanal bellek (virtual memory) ok fazla kulc lanlyor ise, Java Sanal Makinas iin ayrdmz bellek, iletim sisteminin c g s elinde olduundan daha fazla bir deere ayarlanm olabilir; Bu yanl ayar g g s s tel etmek iin iletim sistemi srekli sanal bellee giderek, diskte ve diskten a c s u g fazla okuma/yazmaya sebebiyet vermektedir. Bildiimiz gibi iletim sistemg s leri ellerindeki mevcut gerek bellek kapasistesinden ok daha fazlasn, diski c c sanal bir bellek gibi kullanarak yaratabilirler. Tabii bunun yan etkisi, daha yava alan bir uygulama olacaktr, unk diske yazmak ve oradan okumak, sc s c u gerek bellekten okuyup yazmaktan daha yavatr. c s Bir kurumsal uygulamann diske gidii her zaman veri taban uzerinden s olur, bu sebeple veri tabannn olduu makinadaki kaynaklar ayr olarak takg ibe almanz gerekebilir. Eer bu makinada gereinden fazla diskten okuma ve g g yazma var ise, veri tabannn nbelleini arttrma gndeme gelebilir, ya da o g u uygulamanz tarafndan veri tabanna gnderilen SQL komutlarnda azaltma o ya da dzeltme yaplmaldr. u Uygulamamzn uzerinde alt makinalar takip etmeden nce, bilmemiz c s g o gereken dier bir bilgi, ayn sistemin uzerinde yk yok iken nasl altdr. g u c s g Cunk, belki de su uygulamada (ve uygulama servisinde) deil, uygulamann u c g uzerinde alt makinann ayarlarndadr. Bir iletim sisteminin sfr yk c s g s u altnda nasl altn bilmiyorsak, yk altnda nasl altna dair bir karlatrma c s g u c s g s s yapmamz zaten zor olacaktr, bu sebeple hi yk yok iken sistemimizin nasl c u altn not etmemiz gerekmektedir. c s g 156

ANALIZ ARACLARI

5.3
5.3.1

Analiz Aralar c
JMeter

Yk testlerimiz iin JMeter1 arac kullanabiliriz. JMeter, bir Web uygulau c masnn uzerinde deiik trden ykler oluturmak iin gerekli tm zelliklere gs u u s c u o sahiptir. JMeter ile yk testi yapabilmek iin, web uygulamamz JMetera aynen u c bir kullanc kullanyormu gibi kullandrtmamz lzmdr. Yni JMeter, uygus a a lamamza balanp, bir kullanc gibi sayfalar yklemeli, biraz veri girmeli, g u bireyler silmeli, ve uygulamadan baz listeler almaldr. Yni JMeter, uygulas a may bir sanal kullanc gibi kullanmaldr. JMeter, web uygulamanza sanal bir kullanc olarak gzkmek iin, HTTP o u c protokolunu kullanr. Bir JMetera verilen test plan, hangi sayfann ne zaman, ve hangi bilgiyle arldn belirler. Bu bilgilerin nda test plann c g g sg ileme koyduunuz zaman, JMeter HTTP protokolu ile uygulanza balanacak s g g ve istediiniz veriler ile sayfalarnz gezmeye balayacaktr. Eer test planmz g s g dinamik veriler girebilecek ekilde ayarlamsak, ezamanl kullanc saysn s s s istediimiz kadar arttrabiliriz, ve bylece gerek dnya artlarnda uygulag o c u s mamzn nasl davranacan, nihai ortamda ileme konmadan nce, grebilmi g s o o s oluruz. Test plan hazrlamak iin, iki yntemi takip edebilirsiniz. Ilki, JMetera c o gerekli ar komutlarn elle eklemektir. Ikincisi, siz web uygulamasn kulc g lanrken yaplan tm hareketlerinizi JMetera kaydettirmenizdir. Ikinci yntem, u o doal olarak daha basittir, ve takip edilmesini tavsiye ettiimiz yntem budur. g g o JMeterin kaydettii test plann kullanmadan nce biraz deitirmeniz gerekeg o gs cektir, fakat bu deiiklik ok byk lekte olmayacaktr, ve hereyin elle gs c u u oc s yapld artlardan ok daha basit olacaktr. g s c JMeter Kullanm JMeter programn kurmak iin JMeter sitesinden indireceiniz zip dosyasn c g herhangi bir dizinde an. JMeter ana dosyasnn JMETER_DIR altnda olduunu c g farz edersek, progam balatmak iin JMETER_DIR/bin/jmeter.bat ya da JMEs c TER_DIR/bin/jmeterw.bat dosyasna tklamamz gerekiyor. JMeter ilk baladnda s g Sekil 5.2 uzerindeki gibi bir ekran greceksiniz. o JMeterin grsel kullanm ilk bata deiik gelebilir. JMeter da bir grsel o s gs o birimi srkle/brak (drag/drop) ile hareket ettirip yerine braktnzda, size uu g Sekil 5.3 uzerinde gsterildii gibi bir men ile bir seim sunulacaktr. Gster o g u c o ilen rnekte, Counter adl JMeter grsel birimini HTTP Request Defaults adl o o birimin uzerine brakmz. s Sorulan sorulardan eer Insert Before seilirse, srklediiniz birim, uzerg c uu g ine braktnz birim ile ayn seviyede, ama nce gelmek uzere pozisyonlanr. g o
1 jakarta.apache.org/jmeter

157

5. Performans, Olceklemek

Sekil 5.2: JMeter Al Ekran c s

Sekil 5.3: Srkle ve Brak uu

Insert After seilirse, yine ayn seviyede, ama sonra gelecek ekilde pozisyonc s lanma yaplr. Add as Child seilir ise, bir birim teki birimin ocuu olacak c o c g ekilde dzenlenir. Her birimi her baka birim altna ocuk olarak eklemek les u s c gal deildir; JMeter yeni birimi sadece ocuk kabul eden dier birimlerin altna g c g atmanza izin verecektir. Senaryo Kaydetmek Elle ya da uretilerek girilen test planlar Test Plan altna gitmesini isteriz. Test plann uretebilmemiz iin, uzerinden uygulamamza balanacamz bir c g g proxy servisi yaratmamz gerekiyor. Proxy servisi, Web tarayclarmzdan bildiimiz g bir kavramdr. Internette bir siteye balanrken, genelde o siteye direk olarak g deil, bir proxy uzerinden karz, yni web isteini bizim iin bir proxy (yer g c a g c tutucu) gerekletirmi olur. Bir yerel an Internete balants genellikle bir c s s g g proxy uzerinden yaplr, mesel bir irketin yerel andan dar kan herkes, a s g s c 158

ANALIZ ARACLARI ayn proxyi kullanr. A gvenlii iin bu ekilde bir kullanma ihtiya vardr g u g c s c [8, sf. 85]. JMeter da, aynen yerel a iin hazrlanan bir proxy gibi, bir proxy balatabilir. g c s Bunu yapma amac, o proxy uzerinden web uygulamas test edilirken, yaplan tm hareketleri, GET, POST ilemlerini gzlemleyebilecei bir gei noktasna u s o g cs ihtiyacnn olmasdr. Yni birazdan hazrlamasn reneceimiz JMeter Proxy a og g Server, biz testimizi yaparken tm web isteklerinin ve cevaplarnn uzerinden u ynlenlendirilecei bir gei noktas olacak. o g cs Proxy Server eklemek iin, Workbench uzerinden sa tklama yaparak menden c g u Add | Non-Test Elements | HTTP Proxy Server seeneini sein. c g c

c Sekil 5.4: JMeter Iin Proxy Server Yaratmak Proxynin ayarlarn deitirmek iin, eklenen HTTP Proxy Server birimgs c inin uzerinde tklayarak, ayarlarn yapabiliriz. Mesel Proxy Serverin hangi a port uzerinden servis vereceini tanmlamak istiyorsak, o port numarasn Port g kutusundan girmeliyiz. Genelde, yerel bir JBossta alan uygulamann port c s numaras 8080 olaca iin, Proxy Server iin verilen olaan deeri 8080i g c c g g deitirmemiz gerekiyor. Bu deer iin 8090 kullanalm. Sekil 5.5 uzerinde bu gs g c ayarlar grebiliriz. o Deiecek dier ayar, Target Controller iin Use Recording Controller gs g c ve Grouping altnda Store 1st sample of each group only seenekleridir. Bu c seeneklerden Target Controller, kaydedilen kullanc ilemlerinin nereye c s kaydedileceini belirler. Biz bu kaydedilme ileminin Test Plan altnda bir g s dinleyici tarafndan dinlenip kaydedilmesini istiyoruz. Bylece test planmz, o dinleme ve kaydetme bittikten sonra bizim iin iletilmeye hazr bir test plann c s ayn JMeter penceresi iinde bekletiyor olacaktr. c 159

5. Performans, Olceklemek

Sekil 5.5: Proxy Ayarlar

Once test plannn kullanma hazr bir hle getirmemiz gerekiyor. Ayarlar a yle yapalm ki, test plan uretimi bittikten sonra, uzerinde ufak deiikliklerden o gs s sonra Ilet komutunu verebileceimiz bir yap hazr olsun. Bunun iin nceg c o likle eklememiz gereken, Thread Group birimidir. Bu birim, yk testlerinin ka u c Thread ve ka kere iletileceini kontrol eden bir birimdir. Thread Group eklec s g mek iin, Test Plan uzerinden sa tklama ile Add | Thread Group seimini c g c yapn. Test plannn hangi makinaya ve porta balanacan kontrol edebilmek g g iin, Http Request Defaults adnda her sayfa balants iin ayn olacak c g c olaan deerleri belirleyen bir birim eklemeliyiz. Bu eklemeyi, biraz nce ekg g o lediimiz Thread Group uzerinden Add | Config Element | HTTP Request g Defaults seimi ile yapabiliriz. Ekleme bittikten sonra JMeter ekran Sekil 5.6 c gibi gzkecektir. o u HTTP Request Defaults deerleri imdilik localhost, 8080 ve http olag s bilir. Kullancy kaytlamay localhost:8080 uzerindeki bir uygulama uzerinden yapacamz iin, testi geri alarken (replay) ayn makina ve port deerini kulg c c g landk. Eer kaydedilmi testleri baka bir makina, porta doru ynlendirmek g s s g o istersek, bunun iin test edilecek makinay deitirmek iin HTTP Request Dec gs c faults uzerinden ok basit bir ilem olacaktr. Zaten klasik JMeter kullanma c s kalb budur: Yerel bir JBoss uzerinde test hareketleri kaydedilir, daha sonra, daha gl bir test makinas uzerinde ayn testler geri alnr. uc u c Simdi kayt edici birimi ekleyelim: Thread Group altnda Add | Logic Con troller | Recording Controller ile bir kayt edici eklemi oluruz. Kayt s edici iin hibir ayar yapmamz gerekmiyor. JMeter iin tek nemli olan kayt c c c o edicinin nerede olduudur unk kayt edilecek sayfa istekleri o seviyeye yazlacaktr. g c u Kayt etmeye balamadan nce yapmamz gereken son ilem, Internet taraycmzn s o s 160

ANALIZ ARACLARI

Sekil 5.6: HTTP Request Defaults Ayarlar

uzerinden gei yapaca Proxy Server bilgisini vermektir. Bu Proxy Server, cs g JMeterda tanmladmz Proxy Server olacak. Mozilla Firefox uzerinde proxy g deitirmek iin Tools | Options | Connection Settings ekranna gidin, ve gs c HTTP Proxy deeri iin localhost ve 8090 girin. Bu deerler, biraz nce JMeg c g o ter Proxy Server iin tanmladmz deerlerin aynsdr. Ve dikkat edin ki No c g g Proxy For kutusunda localhost olmasn. Internet Explorer iin ise, Tools | c Internet Options | Connections | LAN Settings altndaki Proxy Server ekrannda Use a proxy server kutusunu sein ve, Address ve Port kutularna c gerekli deerleri girin. Sekil 5.7 uzerinde Mozilla proxy ayarlarn gryoruz. g ou Gzel. Artk kaydetmeye hazrz. Simdi kayt iin unlar yapalm: u c s Web uygulamamz balatalm s JMeterda tanmladmz HTTP Proxy Server ekranndaki Start dmesine g ug basarak, proxy server balatalm. s Taraycmz localhost:8080a ynelterek, uygulammz test etmeye balayalm. o s Test uygulamas olarak rnek kodlar iindeki StrutsHibAdv projesini kulo c landk. Bu uygulamann tam adresi http://localhost:8080/kitapdemo/ main.do adresidir. Bu adrese ilk gittiimiz zaman, ilk ekran yklemesi ile g u arka planda birok ilemin yapldn greceksiniz. Web istei, tarayc proxy c s g o g server uzerinden Web uygulamamza gidecek ve gzlemi yapan proxy server o JMeter olduu iin, yaptmz istek JMeter tarafndan yakalanacaktr. Web g c g istei, JBoss uzerindeki uygulamaya ynlendirilir, ama ondan nce JMeter bu g o o 161

5. Performans, Olceklemek

Sekil 5.7: Mozilla Firefox iin Proxy Ayarlar c

istein ne olduunu Test Plan altnda kaydedecektir (unk Recording Cong g c u troller orada tanmladk). Web istei iini bitirip geri gelir gelmez, Thread g s Group | Recording Controller altnda yeni birimlerin otomatik olarak eklendiini greceksiniz. Sekil 5.8 uzerinde kaydedilen ilemleri gryoruz. Bu g o s ou ilemler, u web isteklerinden uretilmitir: s s s Ana ekrana git Yeni bir araba ekle (araba #1) Bir yeni araba daha ekle (araba #2) Araba #1i sil Araba #2yi yeni bilgilerle gncelle u Garage listesi al Garage #2 uzerine tklayarak altndaki arabalara bak Tm araba listesini Liste seeneine tklayarak gster u c g o Bir senaryoyu kaydettikten sonra onu File | Save Test Plan as men seenei u c g ile diske yazabilirsiniz. 162

ANALIZ ARACLARI

s Sekil 5.8: Kaydedilen Ilemler

s Kaydedilen Testleri Iletmek Kayt edilen web isteklerinin detaylarn, o istein uzerine tklayarak greg o bilirsiniz. Mesel /kitapdemo/add-car.do isteine tklarsak, bu istek iinde a g c hangi parametrelerin gnderilmi olduu sadaki detay ekrannda listenecektir. o s g g add-car.do iin Send Parameters With the Request balnn altnda, lic s g censePlate, available ve size gibi, bir araba yaratmak iin gerekli paramec trelerin FORM iinde gnderilmi olduunu gryoruz. Herey dzgn gzkyor. c o s g ou s u u o u u Not: Bir tek detay haricinde her ey dzgn; Kayt ilemindeki s u u s tek eksik, /kitapdemo/update-car.do iindeki version bilgisinin c kayt edilmemesidir. Bu bilgiyi, o istein detayna girip, Add dmesine g ug tklayarak elle ekleyebilirsiniz. Version deeri iin 0 deerini girin g c g (version konusunun detaylar iin 3.8.3 blmne bakabilirsiniz). c ou u Kayt ilemi tamamlandna gre, senaryomuzu kurumsal uygulamamz s g o uzerinde iletebiliriz. Veri tabanndaki tm car satrlarn temizledikten sonra s u 163

5. Performans, Olceklemek (yoksa ayn licensePlate kimlikli eklenen ikinci car problem kartrd) test c senaryosunu JMeter ana mens Run | Start ile iletelim. uu s Senaryo, Thread Group iinde tanmlanan iletme koullarna gre iletilecektir. c s s o s Bu koullar tek bir threadin sadece bir kez iletilmesini ngryor. Bu ayarlar, s s o ou Thread Group detay ekrannda gzkebilir (Sekil 5.9). o u

Sekil 5.9: Thread Group Detay Thread Group ekranndaki seenekleri daha detayl tarif etmemiz gerekirse: c Number of Threads: Yk testinin ezamanl ka thread ile iletilmesi u s c s gerektiini kontrol eder g Ramp-up Period: Number of Threads seeneinde belirtilen kadar c g threadin, ne kadar sre iinde balatlmas gerektiini buradan ayarlayau c s g bilirsiniz. Mesel eer thread says 10 ve Ramp-Up a g Period 100 ise, 100 tane thread, 10ar saniye aralklarla balatlacaktr. s Eklemek gerekir ki biz yk test senaryolarmzda bu seenei pek kulu c g lanmyoruz. Bunun sebebi, ezamanl aktif sanal kullanc saysnn srekli s u belli bir sayda tutacak trden testlere ihtiya duymamzdr. Bu bilinen u c say kadar bir yk oluturulmas, uygulamamzn ezamanl ka tane kulu s s c lancya dayanabilecei hakknda bize bir kir vermektedir. g Loop Count: Number of Threadsde belirtilen kadar threadin ka kere c arka arkaya iletilecei buradan ayarlyoruz. Mesel 10 threade Loop s g a Count 5 verdiysek, uygulamamz uzerinde toplam 50 thread ilemi ola s s caktr (tabii herhangi bir anda, uygulama uzerinde ezamanl sadece 10 s thread olacaktr). 164

ANALIZ ARACLARI Deiken (Dinamik) Test Deerleri gs g Test planmz bir kere ilettiimize gre, ayn plan, ezamanl birok kuls g o s c lanc (thread) tarafndan ve ustste iletmeyi dunebiliriz. Fakat bunun iin u s us c Thread Group altndaki muhtelif alanlar deitirip tekrar ileterek doru sonu gs s g c alacamz dunyorsak, yanlrz. Eer senaryoyu bu ekilde iletirsek, Hiberg us u g s s nate ve veri taban tarafndan hatalar geldiini greceiz. g o g Bu hatalarn sebebi, birden fazla Car nesnesinin ayn kimlik ile birka kere c eklenmeye allyor olmasdr. Bu da, test senaryosunun statik yaps gznne c s o o u alnrsa, ok normldir. Test senaryomuz, test iinde gml (hard coded) bir c a c o uu licensePlate verisini kullanarak yazld. Eer ayn testi birka threadden g c iletirsek, ayn licensePlateli arabalar, birka kez eklenmeye allacaktr, s c c s ve bu da license_plate kolonu tekil olmas gereken car tablosu iin hatal c bir durumdur! O zaman, ezamanl birok kullancy ayn test senaryosu ile kullanmak iss c tiyorsak, senaryomuza dinamik bir licensePlate kullandrabilmemiz gerekiyor. Oyle ki, senaryoyu ileten her thread, otomatik olarak yeni bir licensePlate s kullanyor olsun. Counter Senaryomuza bu ekilde bir dinamiklii JMeter programnn Counter tekniini s g g kullanarak ekleyebiliriz. Bir Counter, birim olarak eklendii Thread Group g altda, her deiik threadin her dngsnde yeni artacak ekilde tanmlanabilen gs o uu s bir JMeter birimidir. Bu birimi, Recording Controller uzerinden Add | Pre Processors | Counter seenei ile ekleyebiliriz. c g

Sekil 5.10: Counter Countern hangi saydan balayp kaar kaar artacan ayarlamak iin, s c c g c Counter uzerinde tklayarak detaylarna girebiliriz. Ornek iin bizim girdiimiz c g deerler, Sekil 5.11 uzerinde gsterilmitir. g o s 165

5. Performans, Olceklemek

Sekil 5.11: Counter ile Artan Plaka Deikeni gs

Bu ayarlara gre Counter, 1 deerinden balayarak birer birer artacak, ve o g s 10000 ust deerine kadar byle artacaktr. g o Artk elimizde dinamik, deiken bir licensePlate deikeni olduuna gs gs g gre, bu deikeni gereken web istekleri iinde kullanabiliriz. Mesel, elimizde o gs c a iki tane add-car.do istei var, bir istek iin \${licensePlateCounter}-1, g c teki iin \${licensePlateCounter}-2 tanmn kullanrsak, bu istekleri arka o c arkaya iletebilmi olacaz (licensePlateCounter dinamik bir deiken ols s g gs masna ramen, bir tur bitmeden deimez, bu sebeple ayn tur iinde iki farkl g gs c Car iin ayn deikeni kullanmak, yine bir hataya sebep olurdu. O yzden ayn c gs u tur iinde licensePlateCounter her araba iin ufak bir ek ile deitiriyoruz). c c gs Dinamik licensePlate kullanan dier yerler unlardr (ve bunlarn hepsini g s licensePlateCounter kullanacak ekilde deitirmemiz gerekiyor). s gs Test silme ilemi iin biraz nce eklenen licensePlateCounter deikenlerinden s c o gs birini seip, silme detayna girip FORM iinde gnderilen parametrelerc c o den licensePlate iin bu deikeni (mesel \${licensePlateCounter c gs a }-1) girebiliriz. Bylece eklenen arabalardan biri silinmi olacaktr. o s edit-car.do: Ykleme testi iindeki licensePlatei deitirin (silinu c gs memi olan Car iin) s c update-car.do: Biraz nce yklenen Carn gncellenmesi iin, licenseo u u c Platei deitirin. Ayrca, description esinin, yine licensePlategs og Counter kullanarak, dinamik bir deer gndermesini salayn. Bunun g o g sebebi, eer bir nesne uzerinde hibir deiiklik olmazsa, Hibernatein g c gs bu durumu anlayp (dirty check), veri tabannda UPDATE yapmayacak olmasdr (Hibernate ne kadar akll deil mi?). Biz testimizde bir veri tag ban gncellemesi olmasn istediimiz iin, herhangi bir deerin deimesini u g c g gs zorlamak istiyoruz. Bu yzden description esi iin description changed u og c for \${licensePlateCounter} gibi bir ibare kullanabilirsiniz. 166

ANALIZ ARACLARI

Sekil 5.12: Dinamik Plaka Deeri ile add-car.do g

Bu deiikliklerden sonra, test senaryomuzu artk birden fazla thread ve gs birden fazla kere iletmemiz mmkn olacaktr. Tam bir yk testi! s u u u

Randomizer Counter dinamik deerleri, her JMeter senaryosunu ilettiimizde, bizim tanmladmz g s g g balang deerinden balar. Eer balang deeri olarak 1 kullandysak, senarys c g s g s c g omuzu her ilettiimizde \${licensePlateCounter} deeri de 1 deerinden s g g g balayacaktr. Fakat yk testlerimize, bizim senaryomuza zel bir arttan dolay, s u o s her balangta ayn olan bir saya deeri yerine, rasgele (random) olan deerler s c c g g gerekebilir. Bu tr durumlarda, Randomizer adl Pre-Processor birimini kullanabiliu riz2 . Randomizer birimine, Add | Pre-Processors | Randomizer mensnden uu eriilebilir. Randomizer eklendikten sonra, ayn Counter rneinde olduu gibi, s o g g tanmlanan bir deiken uzerinden rasgele saylara eriilebilecektir. Sekil 5.13 gs s uzerindeki rnek bir kullanmda rasgele deerlerin, \${randomVar} adl bir o g deikene atanmas belirtilmitir. Bu deiken, artk herhangi bir HTTP istek gs s gs biriminde rasgele say olarak kullanlabilecektir.
2 Randomizer,tarafmzdan gelitirilmi bir JMeter birimidir. Bu zellii JMetera eks s o g lemek iin, kitap rnek programlar dizini altndaki randomizer.patch yamasn JMeter c o s r m uzerinde uygulamanz gerekmektedir. Yama uygulamas iin A.14 bl m ne baknz. u u u c ou u

167

5. Performans, Olceklemek

Sekil 5.13: Randomizer s Veri Hazrlk Ilemleri Test senaryomuzu iletmeden nce, her seferinde, veri tabann elle temizles o mek gerekiyor. Bu ok klfetli bir ilemdir (Kural #7). Evet, Counter kulc u s lanm ile her ileyi iinde deerler deiiyor, ya da Randomizer kullanm s s c g gs ile ileyiten ileyie bile deiik deerler almamz mmkn, fakat senaryo sos s s s gs g u u nunda her Car silen bir web isteimiz olmad iin, veri tabannda baz car g g c satrlar artk kalm olacaktr. Eer her senaryonun temiz bir veri taban ile s g balamasn istiyorsak, ve eer silme ilemini elle yapmak istemiyorsak, bu s g s ii JMetera yaptrabiliriz. JMetern programlama birimlerinin arasnda, bir s JDBC sorgu iletme birimi de vardr. Bu birime verilen tandk, bildik JDBC s balant ayarlar uzerinden iletilecek bir sorgu sayesinde her test senaryosunun g s banda truncate table car ile tabann temizlenmesini salayabiliriz. s g JDBC birimini yeni bir Thread Group altna koymamz gerekiyor, unk senaryc u omuzu ileten esas Thread Groupu, ezamanl ve birden fazla ileyebilecek s s s ekilde hazrlanm bir gurup idi. Her thread iin veri taban temizlii yaplmasn s s c g istemiyoruz, temizliin sadece bir kez, ve test banda yaplmasn istiyoruz. O g s zaman baa yeni bir Thread Group ekleyebiliriz, ve thread says ve ka s c kere parametrelerini 1 deerinde tutarz. g Bu yeni gurup uzerinde Add | Config Element | JDBC Database Lo gin Defaults adnda yeni bir birim ekleyelim. Veri taban balant bilgilerini g buradan gireceiz. Ornek bir ekran Sekil 5.14 uzerinde grebilirsiniz. g o Balant ayarlar tamamlandktan sonra, iletmek istediimiz sorguyu gireg s g biliriz. Bunun iin ikinci bir JDBC birimi olan JDBC Request birimini kulc lanacaz. Ayn Thread Group altnda Add | Sampler | JDBC Request ile g bu birimi ekleyebiliriz. Temizlik sorgumuzu iletmek iin de, birimin detays c larna girip SQL Query String parametresi iin truncate table car deerini c g girebiliriz. JDBC ayarlarnn bitmi hlini Sekil 5.15 uzerinde grebilirsiniz. s a o Not: JMeterin JDBC ile veri tabannza eriebilmesi iin, gerekli s c JDBC src jar dosyasna ihtiyac vardr. Bu dosyay gelitirme uu u s 168

ANALIZ ARACLARI

Sekil 5.14: JDBC Balant Ayarlar g

Sekil 5.15: JDBC Sorgu Tanm

169

5. Performans, Olceklemek dizininden alp (mesel MySQL iin mysql-connector-java-3.0 a c .16-ga-bin.jar dosyas) direk JMETER_DIR/lib altna atabilirsiniz. Tm bunlar yapldktan sonra, artk Run | Start ile senaryomuzu istediimiz u g kadar thread ile ve istediimiz kere ust uste altrmamz mmkn olacaktr. g c s u u Komut Satrndan Caltrmak s Eer JMeter programn grsel arayz yerine komut satrndan altrmak g o u u c s istiyorsanz, nceden diske kaydettiiniz senaryoyu File | Open ile tekrar o g yklemek yerine, bir senaryoyu kaydedildii ekliyle direk komut satrndan u g s jmeter komutunu -n seenei uzerinden kullanarak iletebilirsiniz. JMETER/ c g s bin dizini PATH iinde ise u komutu kullanmak yeterlidir; c s
jmeter -n -t myscenario.jmx

Performans Verisini Grmek o Yk testinin ilerken ne kadar zaman aldn grmek iin, grsel bir rapor u s g o c o birimi de eklemek mmkndr. Thread Group uzerinden Add | Listener | u u u Aggregate Report seilirse, raporlama birimi eklenmi olacaktr. Sekil 5.16 c s uzerinde grlen sonular, yerel bir makina uzerinde 10 ezamanl threadin 5 ou c s kere arka arkaya iletilmesi sonucunda elde edilmitir. Test makinasnn yerel ols s mas, loglama seviyesinin DEBUG olmas ve StrutsHibAdv projesinin uzerinde optimizasyon yaplmam (imdilik) bir proje olmas sonucunda, 1 saniyede 2.6 s s ilem gerekletirilebilmitir. s c s s StrutsHibAdv projesini nasl hzlandracamz 5.4 blmnde greceiz. g ou u o g

5.3.2

Unix Uzerinde Istatistik Toplamak

Uygulamamzn, uzerinde alt iletim sistemini ne kadar verimli kullandn c s g s g anlamamz iin, iletim sistemi komut satrnda baz programlar kullanarak sisc s temden istatistikler toplayabiliriz. Bu istatistikler, mikroilemci, diskler, iletim s s sistemi nbellei ve virtual memory (sanal bellek) birimleri hakknda bilgiler o g verecektir. Bu bilgileri kullanarak iletim sisteminin ne kadar iyi kullanldn s g (utilized) anlayabiliriz. Bu blmn geri kalannda, Unix iletim sisteminden performans bilgisi ou u s toplamann yntemlerini tanyacaz. Linux iletim sistemi, srelerinizin (proo g s u c cess) performansn takip edebilmeniz iin ok yararl aralar salar. c c c g Komutlar Altta gsterilen komutlar, izledikleri srelere ve iletim sistemin btnne o u c s uu u balangta ufak bir ek yk getirirler, o yzden canl bir sistem uzerinde, zels c u u o likle tekrar eden bir ekilde kullanlmalar uygun olmayabilir. Tavsiyemiz, bu s aralar yk testi yaptnz makinada kullamanzdr. c u g 170

ANALIZ ARACLARI

Sekil 5.16: Yk Testi Sonularn Grmek u c o

S reler (Processes) u c Her srecin CPU kullanm yzdesine (utilization) gre ps kts almak (en cok u u o c kullanma sahip olan en altta olmak uzere) iin kullanlan ps komutu yledir: c so
ps -eo pid,pcpu,args | sort +1n

Bu komut bizi ayr ayr ps ve top kullanmaktan kurtaracaktr. Bildiimiz gibi g top, her sre nosunun (PID) ne kadar CPU zaman yediini gsterir. Fakat u c g o PID, bize bir srec ismi vermez, bu sebeple testiler ayr bir ps ve grep komutu u c kullanarak PIDden script ismi almak zorunda kalyorlard. Gsterdiimiz ps o g sayesinde iki komut yerine bir tane yeterli olmaktadr. vmstat s Iletim sistemin CPU kullanm, sanal bellei, disk istatistikleri ve bo gerek g s c hafza gibi birok deeri vmstat programndan renebilirsiniz. Eer vmstat c g og g <saniye> gibi bir komut kullanrsanz, vmstat bir sonsuz dng iinde verdiiniz o u c g her saniye deeri kadar bekleyecek, ve sonra uyanarak tm istatistikleri tekrar g u toplayacaktr. Altta rnek bir vmstat kts gryoruz. o c ou
procs --------memory-------- ---swap-- -----io---- --system-- ----cpu---r b swpd free buff cache si so bi bo in cs us sy id wa 2 0 0 760628 44344 155940 0 0 14 122 291 3063 49 2 49 0

CPU altnda listelenen, us, sy, id kalemleri, srasyla kullanc, sistem ve bo zaman (idle time) iin harcanan zaman yzdesini gsterir. Bir Java s c u o 171

5. Performans, Olceklemek s uygulamasnn kulland CPU yzdesi, us altnda kacaktr. Iletim sistemg u c inin ekirdek (kernel) iinde harcad zaman sy altnda kar, ve CPUnun c c g c yzde ka zamanda bo durduu ise id altnda gsterilir. u c s g o IO bal altndaki bi ve bo, srasyla, ka bloun tm blok aralarna s g c g u c gnderildii, ve ka bloun aralardan okunduunu gsterir. Bu deerler, bir o g c g c g o g saniyede ka bloun aralara yazlp okunduunu belirtirler. Linux uzerinde bir c g c g blok, 1 kilobayttr (1024 bayt). Dier Unixler uzerinde bir bloun ne kadar g g olduuna man vmstat uzerinden bakabilirsiniz. g Memory altnda free deeri, iletim sisteminin kullanmad ve bo duran g s g s bellek kapasitesini gsterir. Bu bo alan, herhangi bir uygulama iin kullanma o s c hazr bellek lusdr. swpd, o an kullanmda olan sanal bellek (virtual memo c u u ory) byklun gsterir. u u ug u o /usr/proc/bin/pstack Bu komut size Java srecinizin iindeki lwp ytn gsterir. Her Java Threadi u c g o komaya balamadan nce bir lwpye (haf sre/lightweight process) balanmak s s o u c g zorundadr, ve bu komutu ile hangi Threadin hangi sistem ars uzerinde bekc g lediini raporda grebilirsiniz. Btn Threadleri bir soketten okumada, ya da g o uu bir yerel arm uzerinden JDBC srcnz beklediini grebilirsiniz. Bzen c g uu u u u g o a bu gibi bir bilgi yeterli olmayabilir, unk hangi Threadin hangi soket nosunu c u beklediini bu ara gstermez. g c o /usr/proc/bin/pldd Bu komut hangi yerel kodun (native code) JVMinize yklenmi olduunu u s g gstermesi asndan yararldr. Komut, hangi .so dosyasnn JVM srecine o c u dinamik link edilmi olduunu gstererek alr. s g o c s /usr/proc/bin/pags Bu komut, her sre iindeki her lwpnin iaretlerini (ags) ve bekleme duruu c c s munu (wait state) rapor eder. Bu komutu ka tane thread context detirimi c g (switch) olduunu anlamak iin kullanabilirsiniz. Eer her JVM iin birden g c g c fazla CPU var ise, context deitirimi byk bir ihtimalle yksek sayda olags u u u caktr. /usr/proc/bin/ples Ples, herhangi bir srecin ak tuttuu dosyalar gsterir, bylece dosyalarn u c g o o kapanmamas ile alakal olan problemleri takip etmenize yarar. 172

ANALIZ ARACLARI lsof Bir Unix srecinin ak tuttuu dosyalar grmek iin lsofu3 kullanabilirsiniz. u c g o c lsof, pfilesa benzer, fakat daha yararl bir kt verir. c truss -c -p Bu komut, bir srece kar balatlmas ve kesilmesi (interrupt) arasnda sre u s s u c tarafndan yaplm olan sistem rlarn rapor eder. Ornek: s cag
\$ ps PID TTY TIME CMD 11218 pts/5 0:00 ps 11211 pts/5 0:00 bash \$ truss -c -p 11211 ^C (Control-C ile program durdurduk) syscall sys totals: usr time: elapsed: seconds calls errors -------- ------ ---.000 0 0 .000 3.750

5.3.3

Detayl Performans Istatistii Toplamak (Proling) g

Diyelim ki elinizdeki program ok yava alyor. Unixde vmstat ile (ya da c s c s Windows uzerinden Task Manager uzerinden) bakyoruz, ve gryoruz ki maki ou nadaki CPU kullanm (CPU utilization) 100%e gelmi! Fakat (gene varsayalm) s programmz belirli aralklarla Thread.currentThread.sleep() metodunu ileten s trden bir program, ve CPUyu bu kadar zorlamamas gerekiyor. u Acaba programn hangi blm bu kadar CPU zaman alyor? Ya da, daha ou u c genel bir soru: Hangi Java metotu ilemekte en uzun zaman alyor? s Genel Ihtiya c Yukardaki sorunun cevab, Proler adl aralar ile verilir. Elimizdeki problem c iin bir Prolerdan beklediimiz, en acsz ekilde JVMe eklemlenebilmesi, c g s kaydet eklinde bir komut ile btn metot armlarn JVM iinde gzetles uu c g c o meye balamas, dur diyince ham kty bir dosyaya yazmas, ve bu ham s c veriden, daha sonra grsel bir ekilde btn metot armlarn ne kadar zao s uu c g man ald bilgisi ile birlikte gsterebilmesidir. Analiz evresinde bir grsel ara g o o c
3 ftp://vic.cc.purdue.edu/pub/tools/unix/lsof/

173

5. Performans, Olceklemek

Sekil 5.17: CPU Kullanm

ile kullanc btn metotlar ileyite harcad zamana gre sralayarak en uu s s g o yava metotu hemen grebilir. Bu metot da dertlerimizin kaynakland metot s o g olacaktr. Java iin revata birok Proler seenei mevcuttur. Su anda piyasadaki c c c c g biri bedava biri ticari iki kullanl Prolerdan bahsedeceiz. Bedava seenek s g c olarak JDKnin paras olan HProf, ticari olarak ta YourKit Java Proler 4 c adl Proler uzerinde karar kldk. Tabii bu iki paket uzerinden anlatacamz g kavramlar her Proler uzerinde geerli olacaktr. YJP urn ticari olsa da, c u u test etme lisans erevesinde 15 gn bedava kullanlabilir. c c u HProf HProf balamnda CPU, bellek kullanm, vs trden istatistikleri toplamak g u iin, incelenen program iletilirken Java komut satrna -Xrunhprof eklemek c s gerekiyor. Degisik secenekler eklenerek toplanan istatistik tanmlanabilir. Tm liste u iin aadaki seenei kullannz. c s g c g
java -Xrunhprof:help

Mesel, CPU baznda istatistik toplamak iin a c


java .... -Xrunhprof:cpu=samples,depth=6 com.sirket.XYZ

Yukardaki komutu ilettikten sonra, lmek istediimiz kod blmlerini egzs oc g ou ersiz eden testlerimizi iletiriz. s Test bittikten sonra, artk sonular grmek iin, program bitirmek (JVMi c o c durdurmak) gerekiyor (Control-C, kill -9, vs). Ancak o zaman Proler toplad g sonular bir dosyaya yazacaktr. Dosya ismi tanmlanmaz ise, kt dosya ismi c c java.hprof.txt olacaktr. Bu dosya iinde (en altta), en cok zamann harc cand metotlar, en fazlas ustte olmak uzere listelenmektedir. g
4 http://www.yourkit.com

174

ANALIZ ARACLARI
CPU SAMPLES rank self 1 14.96% 2 12.96% 3 11.96% 4 10.00% BEGIN (total = 203235) Fri Jan 21 18:39:44 2005 accum count trace method 14.96% 30394 553 java.net.PlainSocketImpl.socketAccept 14.10% 1002 123 com.sirket.vs..vs.. 14.00% 435 343 com.sirket.vs..vs.. 14.00% 554 564 com.sirket.vs..vs..

Buna gre en ok zaman java.net.PlainSocketImpl.socketAccept iinde o c c harcanm. socketAcceptin stack traceini grmek iin, listedeki TRACE kolos o c nunda verilen numaray alp, java.hprof.txt iinde bataki blmde aramak c s ou gerekiyor. Burada aranacak kelime TRACE 553. Bu da yle gzkebilir: so o u
TRACE 553: java.net.PlainSocketImpl.socketAccept(PlainSocketImpl.java:Native method ) java.net.PlainSocketImpl.accept(PlainSocketImpl.java:353) java.net.ServerSocket.implAccept(ServerSocket.java:448) java.net.ServerSocket.accept(ServerSocket.java:419) sun.rmi.transport.tcp.TCPTransport.run(TCPTransport.java:334) java.lang.Thread.run(Thread.java:534) com.sirket.paket.FilancaClass.metot(FilancaClass.java:222)

En ok zaman harcanan arm zinciri bu olarak gzkyor. Artk kodumuza c c g o u u dalp sorunlu olan blm optimize etmeye balayabiliriz. ou u s Call Stack listesinin derinliini (ka metot gsterileceini) depth=xx kontrol g c o g ediyor. Cpu=samples, rnekleme yntemi ile (her metotun gzlenmedii) trden o o o g u lum yapmak iin kullanlyor. o c c YJP YJPnin JVMe eklemlenebilmesi iin, komut satrndan iletilen java komuc s tunun, YJP uzerinden iletilmesi lazm. YJPyi indirip bir dizine kurduktan s sonra, programmz ilettiimiz .sh ya da .bat dosyas iine u komutlar eks g c s lememiz lazm.
set YJP_JAVA_HOME=c:\j2sdk1.4.2\_04 set JAVA_HOME=c:\j2sdk1.4.2\_04 set PATH=C:\yjp-2.5-build310\bin;%PATH% java -Xrunyjpagent -cp . Test

Java komutundan sonra eklenen -Xrunyjpagent seenei, kontrol YJPye verc g u mektedir. Simdi, YJP grsel programn iletmek iin (kaydet, dur, gster ko o s c o mutlarn vereceimiz program bu olacaktr) YJP_DIZINI/bin/yjp.bat iine g c
set JAVA_HOME=C:\j2sdk1.4.2\_04 set YJP_JAVA\_HOME=C:\j2sdk1.4.2_04

175

5. Performans, Olceklemek c ug u komutlarn ekleyin. Oltumz programa dnelim: YJPnin gzetimi altnda o o iletmek iin, kostur.bat koturalm. s c s
> ./kostur.bat ... c:\\temp>java -Xrunyjpagent -cp . Test [YourKit Java Profiler 2.5] Listening on port 10000...

Bu en son listening mesajn grnce, demektir ki YJP gzetimi altnda proou o grammz iliyor. YJP hem gzetliyor, hem de port 10000 uzerinden balanabilecek s o g bir programa bilgi vermeye hazrlanyor. Mesel YJPnin nyz program bu a o u porta balanacaktr. Simdi o teki ksm YJP_DIZINI/bin/yjp.sh (ya da yjp g o .bat ile) altralm. c s

Sekil 5.18: YJP Balant Ekran g Makina ve port bilgilerini bu programa girdikten sonra, gnderelim. Balandktan o g sonra, start sampling adl bir seenek greceksiniz (sol tarafta). Bunu setikten c o c sonra, YJP numune veri toplamaya balamtr. Bu veri toplamay istediiniz s s g zaman stop sampling komutu ile durdurabilirsiniz. Bu durdurmadan sonra, aadaki gibi bir soru sorulacaktr: Ham veriyi hangi dosya uzerine yazmak s g istiyorsunuz? Yukarda cikti_1 gibi bir isim verdikten sonra, ak sizi direk olarak rapors lama ve analiz ekranna alacaktr. Artk bu ekranda metotlarn ileyi zamann s s grebilirsiniz. ProfileSample rnek kodumuzda, en ok zamann Test.cagir o o c 2() metotunda harcandn gryoruz 9,224 rakam kodun geri kalan tarafna g ou gre ok byk bir rakamdr, ve bylece hain kodu bulmu olduk. o c u u o s ProfilerSample projesinin basitlii bizi aldatmamal. Bu kadar ufak bir g kod iinde, problemli ksm plak gzle de grebilirdik. Fakat dunn ki c c o o us u 1000 metot armnn yapld bir programmz var ve bu programda en c g g yava ileyen noktay bulmammz bekleniyor. Doal olarak nereden bakmaya s s g balayacamz bile bilemezdik. Proler aralar hem bu balangc, hem de s g c s daha detayl analizler iin gereken zellikleri ayn pakette bize sunmaktadr. c o 176

ANALIZ ARACLARI

Sekil 5.19: YJP ile Sonular Kaydetmek c

Sekil 5.20: YJP ile Sonulara Bakmak c

StopWatch Detayl performans lum iin ne kadar grsel ticari, ak yazlm urnn soruo c u c o c u u u nun ustne atsak ta, bazen kendi yazdmz ve kodun istediimiz blmne u g g ou u koyabileceimiz bir ara daha faydal olabilir. Kodun bir ksmn lulebilecek g c o c hle getirmeye, instrumentation ad verilir; O zaman denebilir ki, hazr aralar a c uzerinden yaptmz performans verisi toplama ilemi, tm kodu instrument g s u etmektedir. Bu blmde, sadece istediimiz ksmlar, kendi yazdmz bir inou g g strumentation arac ile yapmay reneceiz. og g Bu ama iin StopWatch adl bir yardmc class gelitirdik. StopWatch kec c s limesinin Ingilizce anlam, spor msabakalarnda kullanlan trden bir lum u u o c saatidir. Bu saatin bir bala bir de dur dmesi vardr, ve bala dmesine s ug s ug baslnca lum (genellikle milisaniye baznda) alnmaya balanr. Dur komut o c s verilince saat durur, ve o anki lulm deeri gsterir. o c us g o Kodlarmzdan istatistik toplamak iin bize gereken saat de, bu ekilde bir c s 177

5. Performans, Olceklemek saattir. Tabii bizim StopWatch classmz, normal saatlere gre baz ek zellikler o o de ierecektir: c Tek bir StopWatch ana class uzerinde, farkl kod bloklar uzerinde lum o c alan farkl saatler aktif olabilmelidir. c Olulen bir bloa birka kere girilince, yeni alnan deerler eskisine ekg c g lenerek, toplamsal (cumulative) lum tutulmaldr. o c Belli aralklarla, bir thread uzerinden, tm saatlerin lum deerleri ekrana u o c g baslmaldr. Bu zelliklere sahip olan bir StopWatch class, u ekilde kodlanmtr. o s s s
public class StopWatch { private static Logger logger = Logger.getLogger("appLogger"); private Calendar startCal; private Calendar endCal; private TimeZone tz = TimeZone.getTimeZone("CST"); private static Thread stopWatchThread = null; public static final String BLOK_1 = "BLOK_1"; public static final String BLOK_2 = "BLOK_2"; ... public StopWatch() { } public class ShowThread extends Thread { public ShowThread() { } public void run() { while (true) { try { Thread.sleep(10000L); } catch (Exception e) { } StopWatch.showAll(); } } } public StopWatch(String tzoneStr) { tz = TimeZone.getTimeZone(tzoneStr); } public void start() {

178

ANALIZ ARACLARI
startCal = Calendar.getInstance(tz); } public void stop() { endCal = Calendar.getInstance(tz); } public double elapsedSeconds() { return (endCal.getTimeInMillis() startCal.getTimeInMillis())/1000.0; } public long elapsedMillis() { return endCal.getTimeInMillis() startCal.getTimeInMillis(); } public double elapsedMinutes() { return (endCal.getTimeInMillis() startCal.getTimeInMillis())/(1000.0 * 60.0); } // ---------------- STATIC SECTION ------------------------public void startThread() { stopWatchThread = new ShowThread(); stopWatchThread.start(); } private static HashMap watches = new HashMap(); private static HashMap values = new HashMap(); private static HashMap counts = new HashMap(); public static synchronized void start(String key) { StopWatch stopWatch = new StopWatch(); if (!values.containsKey(key)) { values.put(key, new Double(0)); counts.put(key, new Integer(0)); } watches.put(key, stopWatch); stopWatch.start(); }

179

5. Performans, Olceklemek
public static synchronized void stop(String key) { StopWatch stopWatch = (StopWatch)watches.get(key); stopWatch.stop(); double old = ((Double)values.get(key)).doubleValue(); int oldCount = ((Integer)counts.get(key)).intValue(); values.put(key, new Double(old + stopWatch.elapsedSeconds())); counts.put(key, new Integer(oldCount + 1)); } public static synchronized void showAll() { logger.debug(values); logger.debug(counts); } }

StopWatch kullanmak iin, lmek istediiniz her kod paras iin bir isim verc oc g c c memiz gerekiyor. Bu ismi, bir sabit olarak StopWatch iinde tanmlayabiliriz. c Mesel, a
public class StopWatch { ... public static final String GET_CARS_ACTION = "GET_CARS_ACTION"; public static final String VIEW_CAR_ACTION = "VIEW_CAR_ACTION"; public static final String GET_GARAGES_ACTION = "GET_GARAGES_ACTION"; ... }

Bu tanmlar ile, uc tane lum blou tanmlam olduk. Bloklarda ne kadar o c g s zaman geirildiini lmek iin, gerekli .java dosyalarna girerek, lumn c g oc c o c u balamas ve bitmesi gereken yerlerde start ve stop arlarn koymamz s c g gerekiyor; Mesel ShowCarDetailAction iine bir lum blou yerletirelim. a c o c g s c u s Olum balatp durdurabilmek iin start ve stop arlarn yle kullanacaz: c c g so g
public class ShowCarDetailAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { StopWatch.start(StopWatch.VIEW_CAR_ACTION); ... // // ilem kodlar s // ... StopWatch.stop(StopWatch.VIEW_CAR_ACTION);

180

ANALIZ ARACLARI

return mapping.findForward("success"); } }

c Olumleri, Actionn execute metotunun giriinde balamak ve dnmeden hemen s s o nce bitecek ekilde koyduk. Daha dar bir alan da lmeyi seebilirdik. o s oc c Toplanan lumleri loglarda ve ya STDOUT ekrannda gstermek iin, uyguo c o c lama baznda tek ayar yapmamz gerekiyor: Uygulama baladnda StopWatch s g iindeki ekrana istatistikleri basan threadi balatmamz lzm. Bunun iin, c s a c ShowThread ismindeki StopWatch iinde tanml bir i class (inner class) kulc c lanacaz. Bu thread, her 10 saniyede bir uyanp, o ana kadar toplanan istatisg tikleri ekrana basmak uzere kodlanmtr. Ekrana baslan istatikler, her lum s o c blou iin, o bloun toplam olarak ka kere arld, ve o blokta toplam g c g c c g g olarak (saniye baznda) ne kadar zaman harcanddr. g ShowThreadi tetiklemek iin, mesel StrutsHibAdv projesinde, AppStartup c a .start metotunda u ary yapabiliriz. s c g
new StopWatch().startThread();

Artk uygulamamz baladnda ekrana (hem STDOUT hem de log dosyasna) s g aadaki gibi mesajlar her 10 saniyede bir baslacaktr. Baz lum deerleri s g o c g grmek iin uygulama uzerinde ok basit bir test yaptk (araba yklemek, detay o c c u grmek, garajlardan araba almak, vs gibi). o
17:02:36,920 INFO [STDOUT] {GET_CARS_ACTION=5.258, GET_CARS_FOR_GARAGE_AC TION=0.09, GET_GARAGES_ACTION=0.03, VIEW_CAR_ACTION=0.02} 17:02:36,920 INFO [STDOUT] {GET_CARS_ACTION=2, GET_CARS_FOR_GARAGE_ACTION =1, GET_GARAGES_ACTION=1, VIEW_CAR_ACTION=1}

Ustteki mesajlara gre, VIEW_CAR_ACTION blou bir kere arlm ve 0.02 o g c g s saniye zaman harcanm, GET_CARS_ACTION 2 kere arlp iinde 5.28 saniye s c g c harcanm ve GET_CARS_FOR_GARAGE_ACTION 1 kere arlp 0.09 saniye hars c g canmtr. s Bu sonular uzerinde hemen bir analiz yapacak olursak, GET_CARS_ACTION c 2 kez arlm olsa bile, bu blokta 5.28 gibi ok uzun bir zaman harcandn c g s c g farkederiz. Bunun sebebi, hi optimize edilmemi StrutsHibAdv projesinin, tac s ban balant havuzlarn (connection pool) anca kullanc ilk istei yaptktan g g sonra kurmaya balyor olmasdr (ilk ekran da arabalar ykledii iin GET s u g c _CARS_ACTION blouna girilir). Bu yzden bu blokta 5.28 gibi ok uzun bir g u c zaman geirilmitir. 2.2.4 blmnde yaptmz tavsiyenin geerli olduunu c s ou u g c g bylece grm oluyoruz: Taban balantlar, nbellekleme gibi bata hazr olo o us g o s mas daha uygun olan ilk yklemeleri, uygulama banda bir ekilde zorlayp, u s s ilk gelen kullancya bu performans bedelini detmememiz gerekmektedir. o 181

5. Performans, Olceklemek

5.4

c Performans Iyiletirmeleri ve Oleklemek s

Bu blme kadar, bir kurumsal uygulama uzerinde yk yaratmak ve kod uzerindeki ou u tkanma noktalarn (bottleneck) bulmak iin kullanlabilecek aralar tandk. c c Eer elimizde beklenen bir performans kriteri var ise, bu kritere ulap ulamadmz g s s g yk testleri sonularna bakarak anlayabiliyor, ve problem yaratabilecek alanu c larda harcanan zaman proler aralar daha detayl bir ekilde alabiliyorduk. c s Bu lumler sonucunda, yaplabilecek baz genel optimizasyon numaralarn o c bu blmde paylamak istiyoruz. Bahsedeceimiz trden genel optimizasyonou s g u lar, JBoss, Hibernate, veri taban ve log sistemi odakl olacaktr. Optimizasyonlar, u balklar altnda ilenecek: s s s 1. JVMe yeterli bellek ayrmak 2. Log seviyesini deitirmek (cunc parti urnler ve kendi kodlarmz iin) gs u u u c 3. JBoss Web ileyicisinin kulland thread saysn arttrmak s g 4. Hibernate al ve kritik baz veri ykleme ilemlerini uygulama banda c s u s s yapmak 5. Hibernate POJO nesneleri ve listelerini, veri taban yerine nbellekten o almak 6. Hibernate POJOlar aras ilikilerde, tembel ykleme seeneini kullans u c g mak 7. Hibernatein ilikileri iin urettii SQLi iyiletirmek iin, fetch=join s c g s c seeneini kullanmak c g 8. Web uygulamamz kme ortamnda altrmak u c s 9. Session Beanlerimizi datk yapda kullanmak g 10. Veri tabann hzlandrmak iin, gereken yerlerde kolon indekslerini eklec mek Genel kural olarak, tkanma noktalarn tamir sreci yle olmaldr: u so o Performans Iyiletirme Metadolojisi: Ilk nce en ciddi tkanma s noktasn bulun ve tamir edin. Sonra bu ilemi tekrar edin. Perfors mans kabul edilir seviyeye gelince, durun. 182

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK

5.4.1

JVM

Java uygulamalarn iletmek iin kullanlan komut satr program java (JAVA s c _HOME/bin altnda), en az ve en ok ne kadar hafza kullanacan seenek c g c olarak alabilir. Mesel en az 100 Megabayt ve en fazla 200 Megabayt isteyen a bir uygulama yle balatlabilir: so s
java -Xms100m -Xmx200m -classpath ... MyApplication

JBoss ortamnda, uygulama servisini biz direk java komutu ile deil, baka bir g s script iinden altrdmz iin, java komutunu kullanan bu scripti deitirmemiz c c s g c gs c g gerekiyor. Bu script JBOSS_HOME/bin altnda olan run.conf dosyasdr; Ierii, paketten kt ekliyle yledir: c g s so
if [ "x\$JAVA_OPTS" = "x" ]; then JAVA_OPTS="-server -Xms128m -Xmx128m" fi

Deitirmemiz gereken -server seeneinden sonra gelen ksmdr. Uygulags c g mamz istediimiz lekte altrmak iin, JVMe iletim sisteminde mevcut g oc c s c s gerek bellek deerinin izin verdii kadar bellek yeri vermeliyiz. Mesel, 1 GB c g g a bellei olan bir Linux servis makinasnda, aa yukar 200 MB kadar yeri g s g iletim sisteminin kendisi kullanr. Geri kalan yerin tamam JVMe verilebilir. s En az ve en ok deerleri ayn olmasnda hi bir saknca yoktur (biz byle c g c o yapyoruz). Ne kadar ezamanl kullanc/ilem iin ne kadar bellek gerektii sorusuna s s c g cevab 5.2.1 blmndeki Kurumsal Webin Altn Kanunu vermiti: Bu oran ou u s balang olarak iyi bir kriterdir. Tabii bu orann oturum ksmn zorlayarak s c 600, 700 rakamlarna kabilirsiniz, fakat belli bir noktadan sonras uygulac manzn optimal ileyii kt ynde etkilenecektir. Dikkat edilmesi gereken s s ou o dier bir nokta, 500 saysnn ezamanl aktif olan oturum saysn gstermeg s o sidir. Bir sistemde 500 tane oturum olmas demek, 500 kiinin srekli, ayn s u anda bir sayfaya tklayp sistem uzerinde bir istek yaratmas demek deildir. g Kullancnn dunme zaman (think-time) olduunu gznnde bulundururus g o o u sak, 500 session, belki 100 ezamanl sayfa isteine tekabl eder. Bu say ok s g u c nemlidir, unk JMeter ile yk testi yaparken Thread Group altnda vermeniz o c u u gereken ezamanl thread says, 500 deil, 100 olacaktr. s g

5.4.2

Log4J

3.3.3 blmnde, JBoss ortamnda Log4J ayarlarn nasl ve nerede yapacamz ou u g tarif etmitik. Performans arttrm iin, bu ayar dosyasnn her tr bilgilendirme s c u mesajna (zellikle DEBUG seviyesindeki mesajlara) izin vermemesi gerekir. Cunk DEo u BUG seviyesindeki bilgilendirme mesajlar, kod iinden en fazla uretilen mesajlardr. c Genelde hata bulmak iin programc tarafndan koda eklenen bu mesajlar, nic hai ortamda ie yaramayacak bir ton mesaj log dosyasna basarlar. O sebeple, s nihai ortamda kapatlmalar gerekir. 183

5. Performans, Olceklemek Bildiimiz gibi Log4J ortamnda bilgilendirme mesajlar logger.debug( g mesaj) kullanmyla baslr. Bir ust seviyede, yni bilgilendirmeden daha a nadir ve daha ciddi olan mesajlar INFO uzerinden, logger.info kullanarak baslacaktr. Hatalar ise, tipik olarak logger.error ile loglanr. Loglama ilemini hzlandrmak iin bizim kullanacamz zellik ise, Log4Jin s c g o loglama seviyesini Java paket baznda kontrol edebilme zelliidir. Bu zellik o g o sayesinde, her Java paketinin hangi seviyede loglamas gerektiini tanmlayabiliyoruz. g Nihai ortamda alan bir servisin, tm paketler iin loglama seviyesini INFOya c s u c ekmesi gerekiyor. Bu ekilde ayarlanm rnek bir log4j.xml dosyas, aada c s so s g grlebilir (bu dosyann bir rneini StrutsHibPerformance projesinde de buou o g labilirsiniz).
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"> <appender name="appAppender" class="org.jboss.logging.appender.DailyRollingFileAppender"> <param name="File" value="\${jboss.server.home.dir}/log/kitapdemo.log"/> <param name="Append" value="false"/> <param name="DatePattern" value=".yyyy-MM-dd"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d] %5p [%t] (%F:%L) - %m%n"/> </layout> </appender> <category name="org.apache"> <priority value="INFO"/> </category> <category name="org.jgroups"> <priority value="WARN"/> </category> <category name="org.hibernate"> <priority value="INFO"/> </category> <category name="org.hibernate.cache"> <priority value="INFO"/> </category> <category name="org.apache.axis"> <priority value="INFO"/> </category> <category name="com.opensymphony.oscache">

184

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK


<priority value="INFO"/> </category> <category name="com.mchange.v2.resourcepool"> <priority value="INFO"/> </category> .... <logger name="appLogger" additivity="false"> <level value="INFO"/> <appender-ref ref="appAppender"/> </logger> </log4j:configuration>

Grldu gibi <category name> ibaresinden sonra, seviyesi set edilmek isteo u ug nen paket ismi veriliyor. Her paketin hangi seviyede loglanaca <level value> g etiketi ile bildiriliyor. Peki ustteki listeye hangi paketleri ekleyeceimizi nereden bildik? Cok ba g sit: Uygulamay birka kez iletip, kitapdemo.log dosyasnda yazlan DEBUG c s mesajlarnn hangi paketten geldiine baktk (Log4J bir mesajn hangi paketg teki hangi classtan geldiini gsterebilir) ve mesajlarn grmek istemediimiz g o o g paketleri, ustteki listeye ekledik. Bir paketin seviyesini deitirdiimiz zaman, gs g o paketin altndaki tm classlarn seviyesi o seviyeye set edilmi olacaktr. u s Nihai ortamda yanl log seviyesinde (DEBUG) alyor olmak, balangta s c s s c yaplan en yaygn performans hatalarndan biridir. Ne zaman 10 saniyede ilemesini s beklediimiz kurumsal uygulamamzn ilk deploy edildikten sonra 3 dakikada g altn grrsek, ilk kontrol etmemiz gereken yerin log seviyeleri olduunu c s g ou g hemen hatrlamalyz. Mesel eer seviyelerini INFOya ekmemiseniz, EHCache, a g c s OSCache ve Hibernate paketlerinin mthi miktarda DEBUG log uretip uygulau s manza diz ktreceine emin olabilirsiniz. Bu paketlerin log seviyesini INFOya co u g getirdiiniz anda, uygulamanz kanatlanp uacaktr. g c

5.4.3

JBoss Threadlerini Arttrmak

Yk testlerinizi gerekletirirken, JMeter Thread Group saymz 150 uzerine u c s ktnzda, JBosstan maksimum thread saysna eriildii ve servisin tkand c g s g g hakknda bir mesaj alrsnz. Bunun sebebi, paketten kt hliyle JBossun c g a HTTP isteklerini karlayan thread saysnn da 150 olmasdr. Tek JVM uzerinde s 150den daha yksek lekte testler gerekletirebilmek iin, HTTP istek karlayc u oc c s c s thread saysn arttrmamz gerekiyor. Bu deiiklii yapacamz dosya, JBOSS gs g g _HOME/server/default/deploy/jbossweb-tomcat50.sar altndaki server .xml dosyasdr. Burada grdunz o ug u
<Connector port="8080" address="\${jboss.bind.address}"

185

5. Performans, Olceklemek
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"

olarak verilen satrdaki, maxThreads iin tanmlanm deeri 150den daha c s g yksek bir deere ekersek, daha yksek lekte yk testlerimizi servis uzerinde u g c u oc u kullanabiliriz. Deiiklikten sonra JBoss servisinizi kapatp amamz gerekecekgs c tir.

5.4.4

s Al Hibernate Ilemleri c s

Uygulamamz balarken eer HibernateSession nesnesi hi arlmaz ise, His g cc g bernate hibir hazrlk ilemi yapmayacaktr. Bu hazrlklar ilemleri arasnda, c s s gereken tm veri taban balantlarnn alp havuza konmas, nesne eleme u g c s dosyalarnn okunmas ve POJOlarn bir nilemden geirilerek kalclk ilemleri o s c s iin hazr edilmesi gibi ilemler vardr. c s Hazrlk ilemlerini tetiklemek iin, HibernateSession iindeki static kods c c larn bir ekilde arlmas gerekmektedir. Bunu yapmak iin en basit yol His c g c bernateSession nesnesinin bir static metotunu armaktr, unk Hiberc g c u nateSession hafzaya alnd an Java kurallarna gre iindeki static blok g o c bir defaya mahsus olmak uzere ileme konur. s HibernateSessioni kullanmak iin uzerinde zararsz bir ilem bulmamz c s lazm: Bu da openSession ve hemen arkasndan closeSession ars olabilir. c g Bu iki ilem bir Hibernate oturumunu hemen ap kapatr, ve toplam olarak s c hibir ey deimemi olur, fakat static blok ileme konduu iin tm Hiberc s gs s s g c u nate hazrlklarnn yaplmas zorlanr. Bu iki ary, AppStartup nesnesindeki c g start metotunun iine koyabiliriz. Ornek kodu StrutsHibPerformance proc jesinde bulabilirsiniz.
public class AppStartup implements AppStartupMBean { .. public void start() throws Exception { HibernateSession.openSession(); HibernateSession.closeSession(); .. } }

Balangta balant havuzlarnn hazrlanmasn zorladmz gibi, baz vers c g g ilerin Hibernate nbelleine alnmasn da zorlayabiliriz. Bunu yapmak iin, o g c uygulama banda uygulamann ska kullanacan bildiimiz nesneleri get ve s c g g HQL sorgular ile hafzaya getiririz; Bylece bu nesneler ayn anda nbellee o o g alnm olurlar. s Bu ilemleri de AppStartup.start metotunda gerekletirebiliriz (nasl olsa s c s bir Hibernate oturumunu am bulunmaktayz, oturumu hemen altndaki satrlarda c s veri yklemesi iin kullanabiliriz). u c 186

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK

5.4.5

Hibernate Onbellek Kullanm

Hibernate kullanan kodlarn JDBC kullanan kodlardan daha hzl olmasnn iki sebebi, Hibernatein urettii SQLin elle yazlan SQLden daha optimal ol g mas ve Hibernatein sk deimeyen POJOlar veri taban yerine nbellekten gs o alabilmesidir. Hibernate, kontrolnde olan POJOlar, gene kendi kontrolnde u u olan get, saveOrUpdate ve delete komutlar uzerinden ne zaman nbellee o g yazacan ve ne zaman oradan silmesi gerektiini ok iyi bildii iin, Hiberg g c g c nate uzerinden nbellek kullanm programc uzerinde ok az klfet getiren bir o c u ilem hline gelmektedir. s a

Sekil 5.21: Onbelleksiz Hibernate

Sekil 5.22: Onbellekli Hibernate

Hibernate ile beraber kullanlabilecek birok ak yazlm ve ticari nbellek c c o paketi mevcuttur. Biz bu blmde EhCache ve OsCache nbellek paketlerini ou o ileyeceiz. EhCache, tek JVMli ortamlarda, OsCache ise, datk mimarilerde s g g kullanlmasn tavsiye ettiimiz paketlerdir. g 187

5. Performans, Olceklemek Genel Ayarlar Onbellek kullanmak iin, hibernate.cfg.xml dosyasnda hangi nesnelerin ve c ilikilerin nbellekleceini belirtmelisiniz. s o g
<class-cache class="org.mycompany.kitapdemo.pojo.Car" region="Simple" usage="read-write"/> <class-cache class="org.mycompany.kitapdemo.pojo.Garage" region="Simple" usage="read-write"/> <collection-cache collection="org.mycompany.kitapdemo.pojo.Garage.cars" region="Simple" usage="read-write"/>

Ustteki tanmlara gre Garage, Car nesneleri, ayrca Garage uzerindeki cars o ilikisinin nbellee alnaca belirtilmitir. Hibernate, sorgulardan gelen sonular s o g g s c da nbellekleyebilir. Bunun iin, Hibernate Query nesnesinin uzerinde seto c Cacheable(true) arsn yapmalsnz, ve Query uzerinde sorgu sonularnn c g c hangi nbellek blgesini (region) kullanacan belirtmelisiniz. o o g
Query query = s.createQuery("from Car"); query.setCacheable(true); query.setCacheRegion("KitapDemoQueries");

Buradaki kullanm, sorgu sonularnn KitapDemoQueries adl bir blgede kulc o lanlmas gerektiini belirtiyor. Sorgu sonularnn nbellek blgesi, aynen POJO g c o o ve nesne ilikilerin blgeleri gibi tanmlanmtr. s o s Sorgu sonular nbelleklemesinin perde arkas yledir: Hibernate, bir sorguc o so dan gelen sonularn sadece kimlik deerlerini nbellekte tutar. Gerek objeler, c g o c ikinci seviye nbellekte tutulacaktr. Bir sorgu sonucunun nbellekten atlmas o o (eviction) POJO nesnelerinden farkl olarak, o sorgu iinde referans edilen c herhangi bir nesnenin deimesi (delete, saveOrUpdate, merge) durumunda gs olur. Bu aslnda olduka kstlayc bir kstastr (tabii ki sistem doruluu iin c g g c byle yaplmas gerekir) ama sorgular nbellee alma/almama kritlerimizde o o g aklmzda tutmamz gereken nemli bir etkendir. o Onbellek Blgeleri o Onbellek paketinin nbelleklenen bir nesneyi ne kadar uzun sre ieride tuo u c taca, ne kadar kullanlmadan kalmasna (idle time) izin verecei, o nesneden g g ka tane nesnenin olmasna (blge byklu balamnda) izin verecei gibi c o u u ug g g ziki ayarlar, hep bir blge baz alnarak yaplmaktadr. Eer ziki ayarlar, her o g 188

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK nesne, her iliki iin ayn olsayd, Hibernate birbirinden deiik olmas gereken s c gs trden nbellek kullanmlarna hitap edemezdi. u o EhCache Hangi nesne ve ilikileri nbellee alnmasn belirttik. Artk kullanacamz s o g g nbellekleme paketini belirtmeli, ve bu nbellek paketine blge tanmlar vero o o meliyiz. Paket olarak EhCache kullanmak iin, hibernate.cfg.xml dosyasnda, c EhCache ile kpr kurabilen bir class belirtmemiz gerekiyor. o u
<property name="hibernate.cache.provider_class"> org.hibernate.cache.EhCacheProvider </property>

EhCacheProvider, Hibernate ile EhCache arasnda balant kuran kpr kog o u dudur. Bu tanmdan sonra, CLASSPATHte bulunmas gereken ayr bir dosya ehcache.xml iinde, her blgenin ziki ayarlarn yapmamz gerekiyor. c o
<ehcache> <diskStore path="java.io.tmpdir"/> <cache name="org.mycompany.kitapdemo.pojo.Car" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> <cache name="org.mycompany.kitapdemo.pojo.Garage" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> <cache name="org.mycompany.kitapdemo.pojo.Garage.cars" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" /> <cache name="KitapDemoQueries" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="0" timeToLiveSeconds="1000" overflowToDisk="false" /> </ehcache>

189

5. Performans, Olceklemek Her nbellek blgesini tanmlarken kullandmz parametrelerin aklamas o o g c yledir: so maxElementsInMemory, bir blge iinde en fazla ka tane birimin o c c tutulan belirtir. g eternal: Blge iindeki birimin sonsuza kadar nbellekte kalp kalmayo c o acan eternal parametresi iin true ya da false vererek ayarlayabilig c riz. Bu deer true olarak belirlenmise, o blgedeki birimlerde deiiklik g s o gs yaplmad srece nbellekte tutulurlar. Ayrca bu durumda timeToIg u o dleSeconds ve timeToLiveSeconds deerlerine baklmayacaktr. Eer g g eternal false ise, timeToIdleSeconds ve timeToLiveSeconds parametrelerinin ayarlar baz alnr. timeToIdleSeconds: Bir nesnenin nbellekte ne kadar kullanlmadan o kalabileceini belirler. Eer bir nesne, nbellekten x saniye kadar alnmamsa g g o s ve timeToIdleSeconds deeri x saniye ise, o obje nbellekten atlacaktr. g o timeToLiveSeconds: Bir nesnenin, kullanlsa da kullanlmasa da ne kadar sre nbellek blgesinde tutulacan belirtir. u o o g OsCache Performans EhCache kadar iyi olan dier bir nbellek paketi, OsCachedir. g o OsCache kullanmak iin, hibernate.cfg.xmlde OsCache ile iletiim kuracak c s balant kodunu tanmlamak gerekiyor. g
<property name="hibernate.cache.provider_class"> org.mycompany.kitapdemo.util.OSCacheProvider </property>

Dikkat: OsCache ile balant kurmak iin org.mycompany.kitapdemo.util. g c OSCacheProvider classn tanmladk5 . Onbellek blge ayarlarn ise, CLASSo PATHte tutulacak oscache.properties adl bir dosyada yapyoruz.
cache.capacity=100000 cache.timeout=-1

OsCache blge ayarlar EhCachee kyasla daha basittir. Tm nesneler ayn o u blge iinde olacaktr. Fakat OsCachede, EhCachede olmayan bir zellik vardr, o c o o da datk bir yapda alabilme zelliidir. g c s o g
5 Hibernate paketinin iinden kan OsCacheProvider kodu, datk modda calmaya c c g s hazr deildir. Kpr kodunu, OsCache programclar deitirerek datk ekilde almaya g o u gs g s c s hazr hle getirdiler. Bu kodu, http://wiki.opensymphony.com/display/CACHE/Hibernate a adresinden, ya da StrutsHibPerformance projesinde bulabilirsiniz

190

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK Datk Mimari ve OsCache g Datk mimarilerde nbellek kullanm, eer kendi hline braklrsa problem g o g a douracak bir durumdur. Mesel datk mimariye hazr olmayan EhCachei g a g datk yapda kullandmz varsayalm. Sekil 5.23 uzerinde bu mimariyi gryoruz. g g ou

Sekil 5.23: Yanl Datk Mimari ve Onbellek Kullanm s g Byle bir yapda, mesel, hem JVM #1in hem JVM #2nin ayn anda o a okuduu bir Car #1 nesnesi olduunu farz edelim. Byle bir yapda, eer g g o g Car #1 nesnesi JVM #1 tarafndan deitirilirse, bu deiiklik JVM #1in gs gs nbelleine ve veri tabanna doru ekilde yansr. Fakat, gncellemeden nce o g g s u o Car #1i kendi nbelleine alm olan JVM #2, bu durumdan tamamen o g s habersiz kalacaktr. Bu durum, uygulamann doruluu asndan tam bir hezag g c met olur, unk nbelleinde tuttuu nesnenin doru olduunu zanneden JVM c u o g g g g #2, veri tabanna gidip en son deeri almas gerektiinden habersizdir. Bylece g g o JVM #2i kullanan bir kullanc, eski ve yanl deerler grecektir. s g o Bu durumu dzeltmek iin, a uzerinden birbirlerine mesaj gnderebilen u c g o trden datk nbellek paketleri kullanmak gerekmektedir. Sekil 5.24 uzerinde u g o byle bir yap gryoruz. o ou OsCache, datk yapda alabilen trden bir nbellektir. Onbellekler arasnda g c s u o haberleme, OsCache iinde JGroups ad verilen bir multicast protokol urn ile s c u u 191

5. Performans, Olceklemek halledilir. Multicast, bildiimiz gibi, yayn bazl bir protokoldr ve yerel alarda g u g ska kullanlan Ethernet donanmnn da yayn bazl olduunu dunrsek, c g us u yayn bazl donanm uzerinde yayn bazl protokoln optimal bir ekilde alabilecei u s c s g sonucuna varrz. OsCachei datk bir yapda altrmak iin tek yapmamz gereken, osg c s c cache.properties iinde gerekli tanmlar yapmaktr. c
cache.cluster.multicast.ip=231.12.21.132 cache.event.listeners= com.opensymphony.oscache.plugins.clustersupport. JavaGroupsBroadcastingListener cache.blocking=false

Bu ayarlar ile, OsCache nbellei iinde deien her nesne iin yerel a uzerindeki o g c gs c g her dier OsCachee multicast ile bir mesaj gnderir. Bu mesaj, deien her g o gs nesnenin dier nbelleklerden silinmesi iin gnderilen bir mesajdr, bylece g o c o o kendi nbelleinden bir nesneyi kaybeden dier JVMler, bu nesnenin gerek o g g c deerini almak iin veri tabanna gitmeye mecbur kalrlar. Bu da istediimizi g c g bir davrantr, unk o nesnenin en son doru hli, veri tabannda olacaktr. s c u g a

Sekil 5.24: Doru Datk Mimari ve Onbellek Kullanm g g

192

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK

5.4.6

Hibernate ve Tembel Y kleme (Lazy Loading) u

Tembel ykleme, iinde veri tayan bir nesnenin (tek nesne ya da nesneler u c s ieren bir List) verilerini o veriye ihtiya oluncaya kadar yklemeyip beklemesi c c u anlamna gelir. Hibernate, 3. versiyondan itibaren, olaan davran olarak temg s bel ykleme yapmak uzere ayarlanmtr. Hibernate get() ya da load() ile bir u s ana nesneyi yklerseniz, bu nesnenin eleri veri tabanndan yklenecek, fakat u og u bu nesnenin bire bir, bire ok, ya da oka ok ilikisinin olduu dier nesnelerin c c c s g g ierikleri yklenmeyecektir. c u Bunun yaplmasnn sebebi, uygulamalarn kullanm dzenine (pattern) baklarak, u genelde bir nesneden, o nesnenin ilikinin olduu her dier nesneye atlans g g madnn bilinmesidir. Eer kullanc, ounlukla, A nesnesinin detaylarna g g c g bakyor fakat Ann ilikide olduu Bnin detaylarna (elerine) hi bakmadan s g og c A nesnesini atyorsa, o zaman A yklenince Bnin otomatik yklenmesi gibi u u bir nsezinin hibir deeri olmayacaktr. Hibernate, bu genel kullanm dzenine o c g u gre bir optimal ayar desteklemitir. o s Fakat, her tr kullanm ekli ve uygulama eidi iin bu doru olmayau s c s c g bilir. A yklenince Bnin detaylarna ihtiya olan artlar iin, tembel yklemeyi u c s c u kapatabilirsiniz. Hibernate, tembel ykleme ayarn class ve iliki seviyesinde u s yapmanza izin verir. Mesel her Garage yklenince onunla ilikide olan Car a u s listesi yklensin istiyorsanz, Garage.hbm.xml eleme dosyasnda u ayar yabau s s bilirsiniz.
<set name="cars" inverse="true" lazy="false" > <key> <column name="garage_id"/> </key> <one-to-many class="Car"/> </set>

Eer bir classn ilikide olduu tm ilikiler iin tembel yklemenin iptal g s g u s c u edilmesini istiyorsanz, class seviyesinde u ayar yapmanz gerekir: s
<hibernate-mapping package="org.mycompany.kitapdemo.pojo"> <class name="Garage" table="garage" lazy="false"> ... </class> </hibernate-mapping>

Eer Car iin 2. seviye nbellei ileme koymusak, lazy="false" kullanm g c o g s s arad deerleri nbellekten alacaktr. Nesne nbellekte bulunamaz ise, veri g g o o tabanndan ek bir SELECT iletilecektir. s 193

5. Performans, Olceklemek

5.4.7

Hibernate Y kleme (Fetching) Stratejileri u

Tembel ykleme iaret edilen nesnelerin ne zaman ykleneceini belirtiyorsa, u s u g ykleme stratejisi nesnelerin nasl ykleneceini belirler. Tembel ykleme u u g u artlarnda, iaret edilen bir nesne nbellekte yok ise, ana nesnenin bir SELECT s s o ile yklenmesinden her iliki iin ek bir SELECT gerekecektir. Bundan ka yoku s c cs tur. Bu da her durumda kt deildir, fakat uygulamamzn kullanm dzeni ou g u her ana nesnenin detayndan sonra her ilikide olunan nesnenin detayn almay s gerektiriyor ise, ek SELECT yntemi veri tabanna eriim asndan optimal olo s c mayacaktr. 9. blmde belirttiimiz gibi veri tabanlar kmelerle almay ou g u c s severler; 10 tane satr ileyen 10 SQL komutu yerine, tek SQL ile 10 satr s ilemek veri tabanlar iin daha tercih edilir kullanm eklidir. s c s Hibernate, ek SELECT problemine 6 zm olarak, fetch="join" seeneini co u c g getirmitir. Bu ayar, eer bir Hibernate ilikisi uzerinde tanmlanrsa, ana ness g s neyi ykleyen SELECTe otomatik olarak bir JOIN ibaresi eklenecektir. Bu JOIN, u ikinci nesnenin ana nesne ile ilikide olan tm satrlarn tek bir kerede ykler. s u u
<set name="cars" inverse="true" fetch="join" > <key> <column name="garage_id"/> </key> <one-to-many class="Car"/> </set>

Bu kullanm test etmek iin HibernateRelFetchSelect projesine bakabilirsiniz. c Testimiz udur: s


Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); Garage garage = (Garage) s.get(Garage.class, new Integer(1)); for (Iterator it = garage.getCars().iterator(); it.hasNext();) { Car car = (Car)it.next(); System.out.println(car.getLicensePlate()); }

Test programn iletirseniz, fetch="join" kullanlmad zaman (Hibernate s g olaan fetch deeri fetch="select" deeridir) u kty grrsnz: g g g s c ou u u
... Hibernate: select garage0_.id as id0_, garage0_.description as descript2_1_0_ from garage garage0_ where garage0_.id=? Hibernate: select cars0_.garage_id as garage3___, cars0_.license_plate as license1___, cars0_.license_plate as license1_0_, cars0_.description as
6 Bu

probleme literat rde N+1 problemi ismi de veriliyor u

194

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK


descript2_0_0_, cars0_.garage_id as garage3_0_0_ from car cars0_ where cars0_.garage_id=? ...

Grldu gibi, Garage ile tek Car ilikidedir, ve ek SELECT problemi yznden o u ug s u u iki tane SELECT uretilmitir. Eer bu SELECT sorgularn teke indirmek istiyor s g sak, fetch="join" ayarn verdikten sonra testi tekrar iletiriz, ve o zaman u s s sonu gelir: c
.. Hibernate: select garage0_.id as id1_, garage0_.description as descript2_1_1_,cars1_.garage_id as garage3___, cars1_.license_plate as license1___,cars1_.license_plate as license1_0_, cars1_.description as descript2_0_0_,cars1_.garage_id as garage3_0_0_ from garage garage0_ left outer join car cars1_ on garage0_.id=cars1_.garage_id where garage0_.id=? ..

Burada tek bir SQL uretildiini gryoruz, demek ki ek SELECT problemi g ou halledilmitir. Car nesneleri, bir left outer join komutu ile artk Garage s ile birlikte tek sorgu ile yklenebilir durumdadr. u

5.4.8

c JBoss K mesi (Web Uygulamalar Iin) u

Bir kme (cluster), birden fazla servis noktasnn (node) birarada almasndan u c s meydana gelen ktledir. Bu servis noktalarnn genelde ortak bir amac vardr. u Bir servis noktas bir bilgisayar da olabilir, ayn bilgisayarda alan birden fazla c s sre (process) de olabilir. JBoss dnyasnda bir kme iki eyi yapar: Ckme u c u u s o Tolerans (Fault Tolerance) ve Yk Datm (Load Balancing). u g Ckme Tolerans bir bilgisayarda kme olduu anda, kullancnn bal o co g g olduu servis noktasnn deitirilebilmesi ve bu deiimin kullancya fark etg gs gs tirilmeden yaplabilmesidir. Web dnyasnda bunun tercmesi kullancnn otuu u rum (session) bilgisinin baka bir makinada her zaman kopyasnn olmas, ve s kme annda kullancnn kopyaya doru ynlendirilmesi ilemidir. co g o s Y k Datm lekleme amal olarak ezamanl kullanclarn ykn biru g oc c s u u u den fazla makinaya datarak tek servis noktalar uzerindeki yk (balanty) g u u g azaltma abasna denir. Ckme Tolerans ve Yk Datm terimlerini birbiri c o u g ile kartrmamak gerekir. s Kmeleme hakknda konuurken telfuz edilen bir dier zellik de, Yksek u s a g o u Mevcudiyet (High Availability) kavramdr. Bu kavram bir kullancnn balanacak g bir servis bulma ansn ve bu servisten gelecek cevap sresinin (response time) s u her zaman mkul erevede olmas gerekliliine/garantisine verilen genel addr. a c c g Ckme Tolerans destei, her zaman Yksek Mevcudiyet anlamna gelir. Ama o g u tersi her zaman doru olmayabilir unk kme tolerans, veri doruluu ile g c u co g g ok yakn alakaldr; Kullanc, arka planda kme olsa da hem kmeyi hissetc co co memeli, hem de o anda girmekte olabilecei verisinde bir yanllk grmemelidir. g s o Finans dnyasnda yaplan elektronik ilemler bunun tipik rneidir. Fakat u s o g 195

5. Performans, Olceklemek kyasla Yksek Mevcudiyet, her zaman veri doruluunu gerektirmez, belli u g g yzdelerde veri yanllna ramen ayakta olan bir bilgisayarlar bulmamz u s g g ihtimali yksek ise, Yksek Mevcudiyete sahibiz demektir. Telco dnyas her u u u zaman veri doruluu gerektirmeyen yksek mevcudiyet iin gzel bir rnektir. g g u c u o Bu blmde, Web uygulamamz tek bir JBoss uzerinden deil, iki JBoss ou g servisinden oluan bir kmede nasl altrabileceimizi reneceiz. s u c s g og g Apache ve JBoss K mesi u Ayn uygulamay birden fazla JBoss uzerinde altrnca, u sorulabilir: Dardan c s s s gelen Web isteklerinin hangi JBossa gideceine kim karar verecektir? Bu sorug nun cevab, Web isteini ilk karlayan servis noktasndan bakas deildir. g s s g Apache Web Server (port 80 uzerinde ilem yapan) Web isteklerini ilk karlayan s s yer olarak, gerekli JBoss servisine aktarma grevini yapabilir. o Apachenin bu grevi yerine getirmesi iin, Apache uzerinde mod jk adnda o c bir eklenti kurmamz gerekiyor. Mod jk kurulduktan sonra, uzerinde elimizdeki tm JBoss servislerini kayt ederiz, ve bylece Apachenin JBoss servislerinden u o haberi olur. Mod jk, JBoss servisleri ile AJP portu ve AJP protokol uzerinden iletiim u s kurar. AJP protokolu, HTTP protokolu gibi Web bilgisi servis etmek iin c yazlmtr, fakat AJP tek bana taraycnza HTML servis etmek iin deil, s s c g Web Server program ile beraber alarak Servlet teknolojisi ile Apache arasnda c s balant kurulabilmesi iin kullanlr. Sekil 5.25 uzerinde byle bir kurulumu g c o gryoruz. ou

Sekil 5.25: Ayn Makinada Kme: Bir Apache ve Iki JBoss u Optimal olan Web ziksel mimarisi, statik ieriin (jpg, gif dosyalar gibi) c g Apache tarafndan servis edilmesi, sadece Servlet ilemlerinin JBossa braklmasdr. s 196

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK Bunun iin tm statik ierik Apache dizinleri iinde olmaldr. Bunun nasl c u c c yaplacan bu blmde greceiz. Ozet olarak lekleme amalarmz iin bir g ou o g oc c c JBoss kmesi, hzlandrma amalarmz iin statik ierikleri Apacheye iletme u c c c s tekniklerini uygulayacaz. g HttpSession Bir Web uygulamasnn HttpSession uzerine bilgi koymas muhtemel olduu g iin, kme ortamnda bile, oturum ball (session anity) kavramn kme c u g g u ortamna tamamz gerekecek. Yni bir kullanc ilk web isteinin karlanmas s a g s iin JBoss #1e gittiyse, ayn oturum altndaki ikinci istei de ayn JBossa c g ynlendirilmelidir, unk hafzada (HttpSession) tutulan bilgiler, o JVM uzerindedir. o c u Fakat oturum ball kullanm, JVMin kmesi durumunda bir zorluk g g co yaratr, unk eer JVM belleinde (HttpSession) nemli baz bilgiler tuc u g g o tuyorsak ve onu kaybedersek, yeni isteklerin mod jk tarafndan teki JBossa o ynlendirilmesi yeterli deildir: Bellekteki bilgilerin teki JVMler uzerinde de o g o tutuluyor olmas gerekir. Yoksa ynlendirmeden sonra yeni JVM uzerinde beko lenen deerler bulunamayacaktr. JBoss, bu problemi, her servisi birbiriyle g yayn bazl bir protokol uzerinden konuturarak zmtr. Her Servlet uzerinde s co us u tutulan HttpSession ierii, ayn kmenin paras olan teki bir JBossa JGroups c g u c o yayn ktphanesi ile kopyalanr. Oturum Kopyalama (Session Replication) iin uu c gereken ayarlar bu blmde greceiz. ou o g Kavramlar anlattmza gre, Sekil 5.25 uzerindeki kmeyi kurmaya balayabiliriz. g o u s Kurmak Apacheyi Linux uzerinde kurmak iin, kaynaklarndan derlememiz gerekiyor. c Alttaki adres
http://godel.cs.bilgi.edu.tr/mirror/apache/httpd/binaries/linux/

uzerinden httpd-2.0.50-i686-pc-linux-gnu.tar.gz adl kaynak dosyay in dirin. Bu dosyay herhangi bir dizinde an. Bu dizine APACHE_SOURCE diyelim. c Simdi aadaki komutlar komut satrndan uygulayn. s g
cd APACHE_SOURCE ./configure --with-layout=Apache --prefix=/usr/local/apache --enable-rule=SHARED_CORE --enable-module=so make make install

Dizin /usr/local/apache, derleme ve install bittikten sonra Apache iler dosyalarnn s bulunaca yer olacaktr. Bu dizine giderek, sonucu kontrol edebilirsiniz: bin/, g 197

5. Performans, Olceklemek conf/ gibi dizinler grmeniz gerekiyor. Test olarak, Apacheyi hemen balatp o s durdurabilirsiniz.
/usr/local/apache/bin/apachectl start /usr/local/apache/bin/apachectl stop

g Mod jkyi de, aynen Apache gibi, kaynaklarndan derleyeceiz. Alttaki adres
http://www.apache.org/dist/jakarta/tomcat-connectors/jk/source

uzerinden jakarta-tomcat-connectors-1.2.10-src.tar.gz paketini indirin. Paketi an (MODJK_SOURCE diyelim) ve bu dizinin altnda, MODJK_SOURCE/jk c /native/ dizinine gidin. Derlemek iin u komutlar kullann: c s
./configure --with-apxs=/usr/local/apache/bin/apxs --enable-EAPI make

Derleme bittikten sonra, MODJK_SOURCE/jk/native/apache-2.0/ altnda mod jknin ktphanesi yaratlm olmaldr. Bu dosyay alp, Apache altna atmamz gerekiyor. uu s
cp ./apache-2.0/mod_jk.so APACHE_HOME/modules

Artk, Apache tarafnda ayarlar yapmaya balayabiliriz. Apachenin kurulmu s s olduu /usr/local/apache dizinine gidelim, ve conf dizini altnda u dosyalar g s yaratalm. Liste 5.1: httpd.conf
# Include mod_jk configuration file Include conf/mod-jk.conf

Liste 5.2: mod-jk.conf


# Load mod_jk module # Specify the filename of the mod_jk lib LoadModule jk_module modules/mod_jk.so # Where to find workers.properties JkWorkersFile conf/workers.properties # Where to put jk logs JkLogFile logs/mod_jk.log # Set the jk log level [debug/error/info] JkLogLevel info # Select the log format JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"

198

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK


# JkOptions indicates to send SSK KEY SIZE JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories # JkRequestLogFormat JkRequestLogFormat "%w %V %T" # Mount your applications JkMount /kitapdemo/*.do loadbalancer # You can use external file for mount points. # It will be checked for updates each 60 seconds. # The format of the file is: /url=worker # /examples/*=loadbalancer JkMountFile conf/uriworkermap.properties # Add shared memory. # This directive is present with 1.2.10 and # later versions of mod_jk, and is needed for # for load balancing to work properly JkShmFile logs/jk.shm # Add jkstatus for managing runtime data <Location /jkstatus/> JkMount status Order deny,allow Deny from all Allow from 127.0.0.1 </Location>

Liste 5.3: workers.properties


# Define list of workers that will be used # for mapping requests worker.list=loadbalancer,status # Define Node1 worker.node1.port=8109 worker.node1.host=localhost worker.node1.type=ajp13 worker.node1.lbfactor=1 worker.node1.cachesize=10 # Define Node2 worker.node2.port=8209 worker.node2.host=localhost worker.node2.type=ajp13 worker.node2.lbfactor=1 worker.node2.cachesize=10

199

5. Performans, Olceklemek
# Load-balancing behaviour worker.loadbalancer.type=lb worker.loadbalancer.balance_workers=node1, node2 worker.loadbalancer.sticky_session=1 worker.loadbalancer.local_worker_only=1 worker.list=loadbalancer # Status worker for managing load balancer worker.status.type=status

worker.node1.lbfactor ve worker.node2.lbfactor parametrelerinin deerine g gre mod jk, hangi kme birimine daha fazla yk aktarmas gerektiini anlar. o u u g Eer node1.lbfactor=100 ve node2.lbfactor=200 olsayd, node2ye node1e g nazaran iki kat daha fazla yk aktarlrd. u worker.loadbalancer.sticky_session=1 parametresi, oturum ball g g (session anity) kavramn kullanacamz gstermektedir (=1) g o Liste 5.4: uriworkermap.properties
# Simple worker configuration file # # Mount the Servlet context to the ajp13 worker /kitapdemo/*.do=loadbalancer

Ayar dosyalar mod-jk.conf ve uriworkermap.properties iinde yk datcya c u g (loadbalancer) iletilmek uzere sadece /kitapdemo/*.do URL dzeninin seilmi u c s olduuna dikkat edelim. Bylece, bata belirttiimiz gibi, sadece dinamik ierii g o s g c g (.do ile biten URLler, yni Struts Actionlar) JBossa iletmi oluyoruz. Geri a s kalan her trl Web isteini Apache karlayacaktr. Bunu, statik ierii daha u u g s c g hzl servis etmek iin yapyoruz. JBoss iindeki HTTP servisi, byk statik c c u u ierik yklerini kaldrmak iin uygun deildir. Apache Web Server bu konuda c u c g en hzl servislerden biridir. Sitemizi oluturan statik ieriin Apache tarafndan karlanabilmesi iin de, s c g s c Apachenin o ierie sahip olmas gerekmektedir. O zaman statik ieriimizi, c g c g gelitirme dizini olan src/pages olarak alp, olduu gibi /usr/local/apache s g /htdocs/kitapdemo altna kopyalamamz gerekiyor. htdocs dizini, Apache iin en ust seviye ierik dizini olarak kabul edilir. Apache ileten localhost c c s makinanz taraycnzdan http://localhost/page.html ile ziyaret edersek, Apache, pages.html adl dosyay htdocs altnda arayacaktr. Artk JBoss servislerini (kmesini) hazrlayabiliriz. Ornek web projesi olarak u StrutsHibPerformance kullanacaz. g 1. Projeyi nce derleyip (A.1 blmnde anlatld gibi) JBOSS/server/ o ou u g default/deploy altna gnderelim. o 2. JBOSS/server/default/all dizininin, JBOSS/server/default/node1 ve JBOSS/server/default/node2 olarak iki kopyasn kartalm. c 200

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK 3. Daha nceden JBOSS/server/default/deploy altna gndermi olduumuz o o s g (derleme ile) kitapdemo.sar projesini, node1 ve node2 dizinleri altna kopyalayalm. 4. Her iki dizinde de, kitapdemo.sar/kitapdemo.war/WEB-INF/classes /web.xml dosyasna girelim ve <distributable/> etiketini u ekilde s s ekleyelim:
<web-app> ... <distributable/> </web-app>

5. A.4.3 blmnde anlatld gibi, node1 ve node1 altndaki JBoss kuou u g ruluunu, deiik portlar kullanmas iin ayarlayalm. s gs c 6. JBOSS_HOME/server/node1/deploy/jbossweb-tomcat50.sar ve JBOSS _HOME/server/node2/deploy/jbossweb-tomcat50.sar altnda olan server .xml dosyalarndaki Engine name="jboss.web" diyen blou yle deitirelim: g so gs
<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node1"> .. </Engine>

ve
<Engine name="jboss.web" defaultHost="localhost" jvmRoute="node2"> .. </Engine>

7. JBOSS_HOME/server/node1/deploy/jbossweb-tomcat50.sar/META-INF ve JBOSS_HOME/server/node2/deploy/jbossweb-tomcat50.sar/META -INF altndaki jboss-service.xml dosyalarnda UseJK komutunun verildii satr bulalm, ve onu yle deitirelim: g so gs
<attribute name="UseJK">true</attribute>

Kme hazrlmz tamamland. Apache, mod jk uzerinden iki JBoss servisini u g tanyor, ve onlarn arasnda yk datm yapmak uzere hazr. JBoss servisu g lerinin her biri de ayr portlarda almak uzere ayarlandlar (kme ortamnda c s u port deiiklii iin A.4.3 blmne baknz). Her iki JBoss da balatldktan gs g c ou u s sonra, birbirleri ile iletiime geerek HttpSession ieriklerini tekine kopyalays c c o acaklar, ve kme durumunda Apache mod jk, yeni istekleri kmemi makco co s inaya ynlendirdiinde, kullanc uygulamay sanki hi kmemi gibi kullano g c co s maya devam edecektir. Kmeyi balatmak iin JBOSS_HOME altndan u s c 201

5. Performans, Olceklemek
bin/run.sh -c node1 bin/run.sh -c node1

komutlarn uygulamalyz. Apache iin ise /usr/local/apache altnda c


/usr/local/apache/bin/apachectl start

c komutunu kullanrz. U servisin tamam ayaa kalktktan sonra, taraycnz g http://makina-ismi/kitapdemo/main.do adresine ynelttiinizde Apachenin o g Web isteini JBosslardan birine ynelttiini ve balang sayfasn bastn g o g s c g greceksiniz. Yk datmn test etmek iin, ikinci bir tarayc an, ve tekrar o u g c c ayn adrese gidin. Bu sefer ynlendirme yaplan JBoss, ikincisi olacaktr. Ckmo o eye dayankll test etmek iin, birinci JBossu Control C ile kertin, ve her g c co iki taraycy da gnceleyin. Uygulamann hibir ey olmam gibi ilemeye deu c s s s vam ettiini greceksiniz. g o Not: JBoss servislerini balattnzda eer s g g
java.net.SocketException: bad argument for IP_MULTICAST_IF: address not bound to any interface

hatas gelirse, Linux servisiniz multicast paketlerini ynlendirmeye o (route) hazr deil demektir [6, sf. 93] . Multicast destei eklemek g g icin, komut satrnda
route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0

komutunu root olarak iletmelisiniz. Ayn komutu srekli iletmeyi s u s hatrlamaktan kurtulmak iin bu kullanm bir balang scriptinin c s c iine koymanz isabetli olur. Ayrca, JVMin IPv6 (internet proc tokol srm 6) kullanyorsanz, yeni bir network hatas kacaktr. u uu c Bu hatadan kurtulmak iin, Linux seviyesinde IPv6 yerine IPv4 kulc lanmanz yeterlidir7 . JBOSS/bin/run.conf iinde JAVA_OPTS deikenine c gs u deeri atamanz yeterli olacaktr s g
JAVA_OPTS="-server .. -Djava.net.preferIPv4Stack=true"

Not 2: Eer JBoss kmesi baladnda ayr makinalardaki JBosslar g u s g birbirini grmez ise, Linux uzerindeki birimleriniz 127.0.0.1 adresini o balanyor olabilir. Bu durumda JBossunuz networkteki dier IPleri g g grmeyecektir. Bunun nnce gemek iin run.conf iinde set edilen o o u c c c JAVA_OPTSa mesel 192.168.1.1 IP adresi tayan Linux makinas a s iin -Dbind.address=192.168.1.1 ibaresini eklemeniz gerekecekc tir.
7 http://wiki.jboss.org/wiki/View.jsp?page=IPv6

202

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK Fiziksel K me Yaplar u Ustte tarif ettiimiz kme kuruluu, hepsi ayn makinada alan bir Apache ve g u s c s iki JBoss servisi uzerinden hazrland. Gerek bir Web sitesinin ziksel yaps, c daha fazla donanm birimi ierecektir, unk lekleme demek, problemin uzerc c u o c ine daha fazla donanm atmak, daha fazla beygir gc ile ezamanl yaplan u u s islem saysn arttrmaktr. Kmenin donanm yaps asndan ounlukla takip u c c g edilen yntem, her JBoss servisinin ayr bir Unix makinas uzerinde olmasdr. o Byle bir yapy Sekil 5.26 uzerinde gryoruz. o ou

Sekil 5.26: Kme: Ayr Makinalarda Bir Apache Iki JBoss u Bu ekle gre, ayr bir makinadaki Apache, ilk istei alarak mod jk uzerinden s o g yine ayr makinalarda olan JBoss servislerinden birine ynlendirmektedir. Bu o da kullanlabilir, ve leklenebilir bir mimaridir. Daha fazla ezamanl kuloc s lancy idare edebilmek iin, JBoss kmesine yeni bir makina eklenir, ve mod jk c u ile kayt ettirilir. Daha da ciddi bir mimari iin, Sekil 5.27deki mimariyi tavsiye ediyoruz. Bu c mimaride, kmedeki JBosslarn kmesine hazr olunduu gibi, Apachelerden u co g birinin de okmesine bile hazrz. Grldu gibi, tek Apache yerine iki Apache c o u ug kullanlmtr, ve her iki Apache de kmedeki tm JBosslardan haberdardr. s u u Iki Apache arasnda seim yapmak iin, Cisco 11150 markasndaki bir switch c c donanmn kullanacaz. Bu switch, aynen Apachenin Java HttpSession seg viyesinde yapkanlk salad gibi, pr HTTP baznda bir yapkanlk salar, s g g u s g yni ayn mteriyi (client) ayn Apacheye ynlendirir. Bu switch, ok basit a us o c bir ynlendirme yapt iin kme ans daha azdr (kyasla Apache bir yandan o g c co s statik HTML servislemesi de yapar). Switchin Yksek Mevcudiyet gerekliliku leri network adminlerinin sorumluluu altnda olacaktr. Biz eer sistemimizi g g 203

5. Performans, Olceklemek bu yazda tarif edilen seviyeye getirdiysek, bir kurumsal teknik mimar olarak kontrolmz altndaki tm noktalar elimizden geldiince salama alm duu u u g g s rumdayz demektir.

5.4.9

EJB K mesi Yaratmak u

4.5 blmnde EJB Session Bean teknolojisini iledik. Bu blmde ilenen ou u s ou s ekliyle EJB Session Bean nesneleri, kendilerini JNDI uzerinden bulan, balanan s g ve elinde referansn tutan d mterilere metotlarn sunabiliyordu. Gerek s us c bir projeye rnek olarak bir Swing uygulamas JNDI uzerinden eriebilecei o s g EJB Session Bean nesnelerinde metot arlar yaparak (CommandHandler c g mimarisinde tek nesne ve executeCommand metotuna) servis tarafna gerekli ileri yaptrd bir yapy dunebiliriz. Sekil 5.28 uzerinde byle bir yapy s g us o gryoruz. ou Bu yap, dikkatimizi ekebilecei gibi, 4.5 blmnde tarif edilen yapdan c g ou u deiiktir. Yeni yapda, Swing uygulamas EJBlere ularken bir akll yer tugs s tucu (smart proxy) uzerinden balanmakta ve yerel (local) JNDI yerine, global g JNDI servisi kullanmaktadr. Yerel JNDI yerine global JNDI kullanlmasnn sebepleri unlardr: s 5.4.8 blmndeki Web kmesi gerekliliklerine benzer bir ekilde, kodou u u s lama basitlii asndan, aran tarafta tek ve herkese ortak bir giri g c c g s noktasna ihtiya vardr. c

Sekil 5.27: Kme: Final Fiziksel Mimari u 204

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK Datc merkez nokta, merkezi bir yer olduu iin, kmedeki birimlerde g g c u olan yke gre, yeni istei yk en az olan EJB servisine ynlendirme u o g u u o ilemini gerekletirmek iin en uygun yerdir. s c s c Giri noktas, kme birimlerinden ayr olduu iin tek kme noktas s u g c co (single point of failure) yapsndan bizi kurtarr. Bir dier deiiklik ise, yerel yerine global ve yksek mevcudiyeti olan g gs u JNDI (HA-JNDI) kullanld zaman, geriye gelen normal bir EJB proxynin g deil, akll bir proxynin olmasdr. Akll proxynin kullanlmasnn sebebi ise, g kme iindeki dier EJB kme birimlerinden haberdar olan bir proxyye olan u c g u ihtiyatr. Ckmeden kurtulma tekniini kullanmak iin byle bir proxyye c o g c o ihtiya vardr. Senaryo olarak unu dunn: Mesel Swing uygulamasnn c s us u a HA-JNDIdan ald, makina #1 uzerinde EJB #1e iaret eden bir eden bir g s proxy olsa ve o srada makina #1 kse, elimizdeki referansn bize hissettirilmeco den kmemi olan makina #2de olan bir EJB #1 kopyasna ynlendirilerek co s o Swing uygulamasnn hibir ey olmamam gibi iine devam edebilmesini isc s s s teriz. Akll proxy, kme kavramndan haberdar bir nesne olarak bu ii baarl u s s bir ekilde yapabilir. s JBoss Uzerinde EJB K mesi Kullanmak u JBoss kullanarak bir EJB kmesi yaratmak iin, uc ey yaplmas gerekiyor. u c s 1. Projenizde EJB ayarlar yapan dosyalardan biri olan dd/jboss.xml iinde c EJBmizin kme hlinde alacan belirtmeliyiz. Bunun iin bahsi geen u a c s g c c dosyada u ekilde bir ayar deiiklii gerekir: s s gs g

Sekil 5.28: Bir EJB Kmesi u 205

5. Performans, Olceklemek
<jboss> <enterprise-beans> <session> <ejb-name>test/MyTestSession</ejb-name> <jndi-name>ejb/test/MyTestSessionBean</jndi-name> <clustered>True</clustered> </session> </enterprise-beans> <resource-managers> </resource-managers> </resource-managers> </jboss>

Bu listede, norml EJBye gre olan tek deiiklik, <clustered> etiketi a o gs altnda True deerinin verilmi olmasdr. Olaan (default) deer olarak g s g g bu etiket, False deerini tayacaktr. g s 2. Kmemize ait olan servisleri run.sh ya da run.bat ile balatmadan nce, u s o iler kodlarmzn JBOSS_HOME/server/all dizinine gnderilmi olmas s o s gerekmektedir. Tabii servisimizi balatrken de sh s run.sh -c all komutunu kullanmalyz. Eer ayn makinada birden fazla kme birimi g u (JBoss servisi) kullanacaksak, A.4.3 blmnde anlatlan port deiiklik ou u gs tekniini kullanmalyz. g 3. HA-JNDI, JBoss uzerinde JNDI servisinden deiik bir porttan servis gs edilir. O yzden HA-JNDI bulan kodlarn baland portun bilinmesi u g g gerekiyor. Bu port deerinin ne olduunu, JBoss balang log mesajlarna g g s c bakarak bulabiliriz. Mesel, aadaki gibi bir al ekrannda a s g c s
.... 17:50:16,237 INFO [SnmpAgentService] SNMP agent going active 17:50:17,739 INFO [DefaultPartition] Initializing 17:50:18,149 INFO [STDOUT] ------------------------------------------------------GMS: address is localhost:1032 (additional data: 14 bytes) ------------------------------------------------------17:50:20,262 INFO [DefaultPartition] Number of cluster members: 1 17:50:20,262 INFO [DefaultPartition] Other members: 0 17:50:20,272 INFO [DefaultPartition] Fetching state (will wait for 30000 milliseconds): 17:50:20,923 INFO [HANamingService] Listening on /0.0.0.0:1100 ...

Bu ekranda HANamingServicein 1100 numaral portta dinlemeye balam s s s olduu bildirilmektedir. Ite bu port, HA-JNDI iin kullanmamz gereken g c porttur. Ayrca kme ortamnda birden fazla makina olabilecei iin, ve u g c 206

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK bu makinalarn kme ihtimaline kar, JBoss HA-JNDI kullanm Conco s text.PROVIDER_URL iin birden fazla makine ismi tanmlamamza izin c verir. O zaman balant kodlarnz u ekilde olmaldr. g s s
MyTestSession beanRemote; InitialContext ic = null; Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces"); p.put(Context.PROVIDER_URL, "host1:1100, host2:1100, host3:1100"); try { ic = new InitialContext(p); Object objref = ic.lookup("ejb/test/MyTestSessionBean"); ...

Bylece host1,host2 ve host3 isimli makinelerde almakta olan HAo c s JNDI servislerinden hangisi ayakta ise ondan bir EJB referans talep edebiliyoruz. lookup yntemi srasyla listedeki her makinadaki HA-JNDIya o gidecek, eer makinay bulamazsa bir sonrakine devam edecektir. g Yanl Mimariler s 4.3.3 blmnde, Web katman ieren mimarilerde EJB kullanmann optimal ou u c olmadndan bahsetmitik. Sebeplerini burada detayl olarak aklayalm; g s c

Sekil 5.29: Yanl EJB Kmesi - Yerel Car Yaplacaksa EJBye Ne Gerek Var? s u g

Web EJByi Yerel Caryor: Sekil 5.29 uzerinde gsterilen yapda, u soru g o s sorulabilir: Eer Web kodlarndan yerel ar yaplacaksa, datk mig c g g maride almaya yarayan EJB teknolojisinin kullanlmas gerekli midir? c s Baz mimarlar tarafndan ileride ayrmamz rahat olsun diye yerel bile arlsa EJB kullanlm olmas, bir seviyede belki geerli olabilirdi, fakat c g s c 207

5. Performans, Olceklemek birbirinden ayr olan Web + EJB mimarisinin baka sebeplerden tr ops ouu timal olmamas, bu tasarmn baarsna glge durr. s o us u Web ile EJB Ayr JVMlerde: Sekil 5.30 uzerindeki ziksel olarak ayr Web ve EJB artlarnda, performans asndan networke her kmzda s c c s ek bir bedel deriz. Bu yzden Web ortamndan ilem mantk kodlarmz o u s EJB iine koymak yerine, dz bir class uzerinden Java import ile kendi c u JVMimize dahil ederek yerel ar yapmamz daha hzl olacaktr. Kodc g lama asndan da dz class kullanmak, tek bir bileen iin Home, Remote c u s c ve Bean classlar yazlmasn gerektiren EJB seeneinden daha az kodc g lama gerektirecektir. Kodlama klfeti argman, yeni JDK 5.0 annotation u u teknolojisi uzerinden EJB 3.0 uzerinden kullanlyor olsa bile geerlidir, c unk bu sefer annotationlarn eklenmesi ve ayar dosyalarnda gereken c u deiiklikler, yerel ar yapld duruma gre ek kod klfeti anlamna gs c g g o u gelecektir. Fakat buna ramen, Web + EJB mimarisi hakknda u ek savunmay da g s bazen iitebiliyoruz: Web + EJB mimarisinde baz kodlar baz kodlardan ziks sel olarak ayrldklar iin, bir parann ku teki paray etkilemez. Bu c c co us o c geersiz bir savunmadr. Son kullancdan balayan bir Web isteini bir zincir c s g gibi dunrsek, bir zincir, sadece en zayf halkas kadar salamdr. A, Byi us u g arr, B Cyi arr ve B kerse, Ann da Cnin de almas hibir anlam c g c g co c s c

Sekil 5.30: Yanl Bir EJB Kmesi - Web Katman ile EJB Konuuyor s u s 208

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK ifade etmeyecektir. Bu yzden ilem mant kodlarnn ayr bir ziksel maku s g inada olmas, kmeden kurtulma asndan hi bir yardmda bulunamaycak co c c bir faktrdr. o u Son iddia, Web + EJB durumunda bir kod beinin (mesel EJB) daha fao g a zla ilem gcne ihtiyac varsa, onun ziksel leklenmesinin ayr yaplabilmesi, s u u oc mesel ek bir EJB makinas ile sadece ilem gc isteyen beklere ilem gc vera s u u o s u u ilebilme iddiasdr. Bu duncede, pr Web mimarisine kyasla, ciddi eksiklikus u ler vardr. Web + EJB ziksel katmanlar ayr olan bir mimarinin pr Web ziku sel katman ieren bir mimariye nazaran ykn optimal ans sfra yakndr. c u u u s Bunu matematiksel olarak yle ispatlayabiliriz. so Datk Mimari Performans Teoremi 5.4.1. Pr Web mimarisinde olan g u belli bir yk altndaki n N makina, kod ierisinde web iin w(w R, 0 w u c c 1), ilem mant iin ise e(e R, 0 w 1) kadar zaman harcamaktadrlar. s g c Ayrca e + w = 1 olduunu farz ediyoruz. g Pr Web kodlarn Web iin ayr, ilem mant iin ayr EJB ziksel u c s g c makinalara geirdiimizde (ki Web makinalarnn says f w N, EJB makic g nalarnn says f e N olsun) tam kullanm gren (fully utilized) tek dalm, o g f e = en olduu artlardadr. Ayn ekilde Web iin tam kullanm f w = wn g s s c artlarnda olur. Dier tm muhtemel dalmlarda makinalarn bir ksm her s g u g zaman az yklenmi (underutilized) dier ksm da gereinden fazla yklenmi u s g g u s (overutilized) olacaklardr. Kant. Bir makina zamanna 1 deeri verelim. O zaman pr ziksel Web artlarnda g u s tm makinalarda harcanan ilem mant makina zaman, e n olarak hesau s g planabilir. Ayr ziksel Web ve EJB makinalarna geilince, her EJB makinas c bana den makina zaman ise s us en fe

Eload =

(5.1)

olarak gsterebiliriz. Eload deerinin 1 kmas iin tek yol, grldu uzere, o g c c o u ug f e = en olduu artlarda olacaktr. Dier tm muhtemel dalmlarda, ustteki g s g u g formln bleninde yeralan f e deeri, blmde olan e nden ya byk ya da uu o g ou u u kcuk olaca iin sonu 1den ya byk ya da kuk olacaktr. Ayrca f enin u g c c u u uc e ne eit olmas da duk bir olaslktr unk f e bir doal say, e n ise bir s us c u g gerek (real) saydr. O zaman EJB makinas ya az kullanlyor olacak, ya da c boulacaktr. g Eload un 1den kuk kmas art da iyi deildir, unk bu f enin e nden uc c s g c u byk olduu artlarda olur ve bunun sonucu Wload un 1den byk kmasdr, u u g s u u c bu da Web makinalarnn boulduu anlamna gelir. Bunu yle ispatlayabiliriz; g g so 209

5. Performans, Olceklemek

f e

>

en

(5.2) (5.3) (5.4) (5.5) (5.6) (5.7) (5.8)

f e > (1 w) n f e > nwn n fe < w n f w < w n unk f e + f w = n c u wn Wload = fw Wload 1

Eer bu teorinin, tersi ynnde ilerlesek, yni tam kullanm (fully utig o u a lized) Web+EJB mimarisini pr Web mimarisine geirirsek, o zaman dalmn u c g sancsz ekilde dzgn olacan grrdk (bu teori, basitlii sebebinden ispats u u g ou u g lanmayacaktr) unk ayr ziksel katmanlardan tek katmana gei yapyoruz, c u cs ve Web ile ilem mant kodlar ayn JVM iindedir. Bu durumda yk datm s g c u g iin tek gereken, Apachenin kullanc ykne gre gereken ynlendirmeyi yapc u u o o masdr. O zaman u sonuca varyoruz: Kullanabilecek en az donanmla, Web s + EJB mimarisi sadece ok kuk bir ihtimalle (neredeyse sfr) pr Web mic uc u marisiyle ayn performans gsterebilecektir. o Web + EJB kullanmnda pr Web kullanmna nazaran donanm ihtiyac, u bir makina zaman kadar olsa bile, teorilerin ispat srasnda yok farzettiimiz g bir gereklik daha vardr. Teoride network yavalatma faktrn (latency) sfr c s ou u olarak farz ettik. Fakat, gerek dnyada ayr ziksel EJB katmanna network c u uzerinden gitmek, uygulamamz uzerinde kesinlikle yavalatc bir faktr ola s o caktr. Sadece bu sebep iin bile Web ortamnda datk nesneler kullanlmas c g uygun deildir. g O zaman, rnek olarak 6 makinay 3 Web 3 EJB olarak ayrmak yerine o (Sekil 5.30), 6 makinann hepsini Web (ve onun import ile dahil edip ard c g g ilem mant kodlarna) ayrmak daha iyidir (Sekil 5.31 -ki bu mimari 5.27 s g uzerinde gsterilen ideal yap ile ayndr-). o Dardan balananlarn ayn anda hem Web hem zengin nyz (mesel s g o u a Swing) olabilmesi artlarnda bile tavsiyemiz, Web uzerinden EJBye balanlmamasdr. s g Bu artlarda ilem mant kodlarn pr Java kodlarna ayrp hem Webden s s g u hem EJBlerden import ederek armak, Web ziksel katmannn EJB katc g manna ar yapmasndan daha optimal olacaktr. c g

5.4.10

Veri Tabannda Indeks Kullanm

Bir kurumsal uygulamann optimal almasnda, o uygulamann veri tabannda c s gerekletirdii sorgularn performans ok nemlidir. Eer bu sorgularn ne c s g c o g 210

PERFORMANS IYILESTIRMELERI VE OLCEKLEMEK kadar hzl ltn anlamak istiyorsak, ncelikle sorgularn ne olduunu grmeliyiz. ca s g o g o Bunun iin hibernate.cfg.xml dosyasnda c
<property name="show_sql">true</property>

ayarn yapmalyz. Bu ayar, Hibernatein urettii tm SQL sorgularn ekrana g u basacaktr. Bylece yava ilemesi muhtemel olan SQLleri gzmzle greo s s o u u o bilmi oluruz. s Fakat, eklememiz gerekir ki, artlarn %99unda Hibernatein urettii SQL, s g bizim elle yazacamz SQLden daha optimal olacaktr. Ayrca Hibernate arka g planda, mesel Oracle artlarnda bind parameters gibi hzlandrc teknoloa s jileri kulland iin, sorgu iletim hz stored procedure hzna bile eit hle g c s s a gelmektedir. Yni, iin pr Hibernate tarafnda bir problemimiz olmayacaktr; a s u Hibernatee has optimizasyon numaralar bu yzden nbellekleme, fetching u o ayarlar gibi baka bir seviyede yaplr. s Eer tm optimizasyonlara ramen Hibernate veri eriimini yava olduunu g u g s s g gzlemlersek, sebep, veri tabannda eklenmesi unutulmu indeksler olabilir. o s Indekslerin yetersiz olmas artnda zaten SQL ister uretilsin, ister elle yazlsn, s yava alacaktr; En alt seviyedeki veri taban gerekli ekilde optimize edilmemitir. sc s s s Veri tabanlarn optimize etmek iin, Hibernatein urettii SQLin WHERE c g blmnde kullanlan ltre artlarna bakabiliriz. Bu ltre artlarnda kulou u s s lanlan kolonlarn (mesel bir SQL iinde kullanlan her kolonun kombinasyonu) a c iin bir indeks var mdr? Eer c g
... WHERE KOLON1 = 22 KOLON2 = VS VS ;

gibi bir SQL uretilmi ise, KOLON1 + KOLON2 kombinasyonu uzerinde bir indeks s olmaldr. Eer indeks var ise, bu indeks ile WHERE ltre artlar uyum gsterdii g s o g anda veri taban bu indeksi ileme sokacaktr. s

Sekil 5.31: Doru Web Kmesi g u 211

5. Performans, Olceklemek Gzle kontrol yerine, gerekli yerde indeks olup olmadn anlamak iin o g c mekanik bir yntem de takip edebiliriz. Her veri taban urnnde bir SQL sorgu o u u analiz program mevcuttur, bu program bir sorgunun gerekli indekslerin kul lanp kullanmadn gsterebilir. Indeks kavramn, analiz yntemini, ve her g o o taban urn iin bunlarn nasl kullanldn ayrntl ekilde 9.2.9 blmnde u u c g s ou u okuyabilirsiniz. Indeks eklerken dikkat edilmesi gereken bir husus, sadece ve sadece gereken kolon kombinasyonu iin indeks eklememizin gerektiidir. Indeksler, dier pek c g g ok eyin aksine, ne kadar fazla olursa o kadar iyi olan katklardan deildirler, c s g unk veri taban bir tabloya her yeni satr eklediinde o tablo uzerindeki olan c u g indeksleri gncellemeye de mecburdur, ve bu gncelleme ileminin bir hz beu u s deli vardr. Bu sebeple eer bir tabloda gereinden fazla indeks var ise, SEg g LECT ilemimizi hzlandrm olsak bile, bu sefer INSERT ilemimizi yavalatm s s s s s oluruz. Indeksleme ilemini kararnda yapmalyz; O zaman indeksler perfors mansmz arttran nemli bir faktr olabilirler. o o

212

Bl m 6 ou

Sonu Ortam c

Bu Bl mdekiler ou Sonu ortamna kod gndermek c o slemde olan bir kurumsal program kontrol etmek I

213

6. Sonuc Ortam

urumsal uygulamz yazp, test ettikten sonra, uygulamamz ileme s amak iin iler kodlarn sonu ortamna gndermemiz gerekir. Kitabmzda c c s c o tavsiye edilen sonu ortam, iletim sistemi olarak, Unix (Linux, Solaris) c s sistemleridir. O zaman kurumsal uygulamamz Unix uzerindeki bir JBoss uzer ine gndermek iin, baz yntemler kullanmamz gerekecektir. Bu yntemlere o c o o deployment bal altnda bakacaz. s g g Kod gnderildikten sonra (ciddi sonu ortamlarnda) dier bir problem ile o c g kar karya geliriz. Bir kurumsal uygulamay sonu ortamnda gerek kuls s c c lanc yk altnda iletmek, test ortamnda iletmekle ayn deildir. Komut u u s s g satrndan elle balattmz bir program, eer kerse ne olacaktr? Modern bir s g g co kurumsal uygulamann uzerindeki gereklilikler dunlrse (haftann 7 gn ve us u u u u her gnn 24 saati ayakta kalmasnn beklediimiz sistemler) onlarca Unix u u g makinasnn oluturduu bir kme ortamnda, sadece run.sh ile balattmz s g u s g servislerin izlenemez, ve takip edilemez bir halde olduu sonucuna varrz. Bu g sorunu izleme (monitoring) bal altnda zeceiz. s g co g

6.1

Kod Gnderimi o

Baz seminerlerimde kullandm bir ziksel mimari rnei vardr: Bu sitenin g o g kulland ziksel mimari, kme hlinde alan 20 tane Unix makinas ieriyor g u a c s c diyerek baz donanm istatistiklerini dinleyiciye sunarm. Bunu duyan katlmclardan biri bazen u soruyu sorar: Biz 4 makinay zor idare ediyoruz, bu adamlar 20 s makinay nasl idare ediyorlar?. Bahsedilen say hakikaten byk bir saydr. Fakat rnei verilen trden u u o g u bir yapy idare eden adminin kulland o ufack teknii duyunca, sorunun g g cevabnn aslnda ne kadar basit olduunu anlarsnz . Mesel kitapdemo.sar g a adl Web paketimizi, host1, host2, ... , host100 olarak isimlendirilmi 100 s tane makinann /usr/local/jboss/server/all/deploy dizini altna kopyalamamz gerektiini dunn (her makinada JBossun ayn yere kurulmu g us u s olduunu farz ediyoruz). Bu kopyalama ilemini, eer dzeninizi iyi kurmusanz, g s g u s u ekilde yapabilirsiniz (sh scripting dili ile) s s Liste 6.1: sendcode.sh
LIMIT=100 for ((a=1; a <= LIMIT ; a++)) do scp kitapdemo.sar "remoteuser@host\$a:/usr/local/jboss/server/all/deploy" done

Ya da Windows BAT ortamnda Liste 6.2: sendcode.bat


@echo off FOR /L %%n IN (1,1,100) DO call :copying %%n

214

Kod Gnderimi o
goto end: :copying scp kitapdemo.sar remoteuser@host%1:/usr/local/jboss/server/all/deploy :end

Iste bu tek script ile paketimizi 100 makinay tek seferde kopyalam olduk. s Peki bu nasl oldu?

6.1.1

SSH ve SCP

Bir makinadan dierine hem ifresiz hem de gvenli bir ekilde girip, orada g s u s komut iletmek, ya da oraya dosya kopyalamak iin iki program vardr: ssh ve s c scp. Kullanmak iin komut satrndan (ssh iin) c c
ssh host1 -l remoteuser

komutunu kullandnzda host1 adl makinaya remoteuser kullancs uzerinden g login etmi olursunuz. Ya da uzak makinada bir komut iletip sonucunu kendi s s makinanza almak isterseniz (mesel ikinci makinada listeleme komutu olan ls a iletelim), unu yaparz s s
ssh host1 -l remoteuser ls

Eer uzak makinaya bir dosya kopyalamak istersek g


scp file.txt remoteuser@host1:/tmp

Bu komut ile uzaktaki makinaya sanki yerel dizinlerimiz arasnda dosya kopyalyormu s kadar rahat bir ekilde bir dosya kopyalayabiliyoruz. Girite bahsettiimiz bas s g sit teknik ite budur. ssh ve scp bir kez kurulduktan sonra, uzaktaki makina, s yerel makinanzn bir uzants hline gelir. Bir makinay uzaktan idare etmek a demek, ya bir dosya deiimi, ya da bir komut iletmek demek olduu iin, bu gs s g c iki program kullanarak uzaktaki bir makinada yapamayacamz ey yoktur. g s

SCP

215

6. Sonuc Ortam Sifresiz Kullanm Kurmak Eer sshi hibir ek ayar yapmadan kullanrsanz, (ilk kurduumuz haliyle) g c g her kullannzda size bir ifre sorulacaktr. Ayn ekilde scp komutu da byle s s s o davranr. Fakat, biz mesel yz tane makina iin arka arkaya scp ya da ssh a u c kullanmamz gerekecei iin, ifre isteme ilemini iptal edip, gvenlik kong c s s u troln kullancya sorulmayan baka bir ekilde yapmamz gerekiyor. Bu yntem u u s s o de, ak / gizli (public / private) anahtarlar kullanarak yaplan gvenlik konc u troldr. u u Windows uzerinde ssh ve scpnin iler kodlarn kurmay, A.8 blmnde s ou u bulabilirsiniz. Linux uzerinde ssh ve scp genellikle otomatik olarak kurulur, eer kurulmamsa, Linux kurulum disklerinizde bu program bulabilirsiniz, ya g s da admininize bu programlar kurdurabilirsiniz. o Ak / gizli anahtar kurulumunu yapmak iin unlar yapn: Ilk nce kod c c s gnderimi ya da uzaktan idareyi yapan yerel makinamz tantan bir gizli o anahtar, bir de ak anahtar uretmemiz gerekiyor. c
\$ ssh-keygen -t rsa

Sorulan sorular iin hi cevap girmeden ENTERe basarak gein. Bu bittikten c c c sonra, \$HOME/.ssh/ dizininiz icinde 2 dosya greceksiniz. Bu dosyalar id_ o rsa.pub ve id_rsa dosyalar olacaktr. HOME deikeninin nerede olduunu kogs g mut satrndan Unix/Cygwinde echo \$HOME ile renebilirsiniz. Windowsda og dosyalarn nereye yazld OpenSSH tarafndan zaten ssh-keygen sonunda g size bildirilecektir. Biraz nce uretilen dosyalardan id_rsa, gizli anahtarnzdr. Dosya id_ o rsa.pub ise ak anahtarnzdr. Simdi, id_rsa.pub kaydndaki ak anahtar, c c uzaktan erieceiniz servis bilgisayarna FTP ya da scp ile gnderin (scp kuls g o lanrsanz, -imdilik- ifre girmeniz gerekecek tabii ki). Sonra, uzaktaki bilgisas s yardaki kullanacanz kullanc hesabna girin, hesabn ust seviyesinde \$ g HOME/.ssh/ dizini altna id_rsa.pub kaydn brakn. Sonra, servis sisteminde
cat > \$HOME/.ssh/id_rsa.pub >> authorized_keys

komutunu caltrn. Kurulu ilemi bundan ibarettir. Bu son ilemden sonra s s s s artk uzaktan ilettiiniz ssh ve scp ilemleri ifresiz bir ekilde iinizi yaps g s s s s manza izin verecektir. Ak anahtarmz servis makinasna eklemek iin, Unix cat komutu ile c c >> ilecini kullandmza dikkat edelim. Bu demektir ki, birden fazla .pub s g dosyasna tek bir authorized_keys dosyasna ekleyebiliriz (ve birden fazla kullancy desteklebilmek iin bunu yapmamz gerekir). Bylece ayn makinaya c o erien birden fazla erien kii, ayn servis makinasna ve ayn kullancya deiik s s s gs ak anahtarlar ile eriebilir. c s Eer ssh kullanmnzda problem karsa (probleme gre) unlar yapag c o s bilirsiniz: 216

Kod Gnderimi o Servis tarafndaki authorized_keys dosyasnn gvenliinin ak olmau g c mas gerekir. Eer dosyann Unix baznda gvenlii ok aksa, sshd g u g c c balanmaya alan ssh ya da scp komutunu bir ifre girmeye zorlayg c s s acaktr. authorized_keys dosyasnn yeterince kapal hale getirmek iin c
chmod 600 authorized_keys

ve bir ust seviyedeki .ssh dizini uzerinde


chmod 700 .ssh/

komutlarn kullanmak gerekebilir. SSH balanamama durumu var ise, problem sunucu bilgisayarnda sshd g programnn ilemesi olabilir. ps -eaf | grep sshd ile bunu kontrol s edebilirsiniz. Balanan bilgisayarlarda Cygwine zel bir problem (Windowsda) udur. g o s Cygwin ssh program (OpenSSH), gizli anahtarn uzerindeki eriim hak s larnn kullancya zel olmasn istiyor. Bu normal tabii unk bu o c u anahtar gizli, ve her kullanc tarafndan okunamamas lzmdr. Hata a yle olacaktr: so
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@ WARNING: UNPROTECTED PRIVATE KEY FILE! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Permissions 0644 for /cygdrive/h/.ssh/id_rsa are too open. It is recommended that your private key files are NOT accessible by others. This private key will be ignored.

Hi problem degil (diye dunyoruz) chmod kullanrsak i biter (blm c us u s ou 10.2.1). Tek problem, Windows ve Unixin eriim haklar yntemlerinin s o birbiri ile uyumamasdr. chmodu altrdnzda, komut bir ey yapm s c s g s s gibi geri gelecek, fakat dosyada bir deiiklik olmayacaktr. Unix dosya gs haklarnn Cygwinde simule edilmesi iin, cygwin.bat iine (CYGWIN c c /bin/ altnda) unu eklemek lazmdr. s
set CYGWIN=tty ntea

Bundan sonra
chmod 0600 id_rsa

komutu dzgn ileyecektir. u u s 217

6. Sonuc Ortam

6.2

s Uygulama Ileyiini Kontrol Etmek s

Kurumsal uygulamamz oluturan servis programlarmzn uzun sre ayakta s u kalmasn ve ilem yapabilmesini isteriz. Eer iletim sistemi hatas, donanm s g s przleri gibi hatalar yznden servis srelerinde kme olursa, sektrde yaygn uu u u u c co o bir metot km olan servisin otomatik olarak ayaa kaldrlmasdr. Bu ii yaco us g s pan en unl ticari program olan AutoSys, ken bir program tekrar balatmak, u co s kme birka kez tekrar ederse olursa belli bir eik deerinden sonra tekrar co c s g balatmay brakp durumu sorumlu bir kimseye e-mail ile bildirmek, ya da s zamanl (scheduled) bir ekilde belli zamanlarda bir program iletmek gibi s s nemli grevleri yerine getirebilir. o o Kitabmzda bedava / ak yazlm yelpazesinden bulunup kullanlabilen c zmleri tavsiye ettiimiz iin, ticari bir urn olan AutoSys yerine bizim co u g c u yazdmz iki Perl scriptini tavsiye edeceiz. Bu scriptler AutoSysin sre g g u c izleme zelliini tayan ufak programlar olacaklardr. AutoSysin zamanl altrma o g s c s zellikleri yerine de, Unix cron programn (blm 10.5) kullanabilirsiniz. o ou

6.2.1

Blok Eden Servis Scriptleri

Blok eden servis programlarndan kastmz, balang komutu verilince kendini s c n plana alan trden servis programlardr. Bu tr programlarn kme duruo u u co munu kontrol etmek istiyorsak, servisi balatmak iin balatc program (run. s c s sh gibi) elle balatmak yerine, bir takip edici program uzerinden balattrtmamz s s gerekmektedir. Bu kontroll balatmdan sonra, eer kontrol edilen program u s g herhangi bir sebeple geri gelirse, kontrol eden program bir kme durumu co olduunu alglayabilecektir. g Alttaki jobRunner.pl adl Perl scriptini bu amala kullanabiliriz. c Liste 6.3: jobRunner.pl
#!/usr/bin/perl use Net::SMTP; \$argCount=\$#ARGV + 1; die "Usage: perl t.pl <maxRestartCount> <wait> " . "<jobname> <progname>\n" if (\$argCount != 4); \$maxRestartCount = \$ARGV[0]; \$wait = \$ARGV[1]; \$jobName = \$ARGV[2]; \$jobProg = \$ARGV[3]; print "\$wait";

218

UYGULAMA ISLEYISINI KONTROL ETMEK


# run the program \$code = system(\$jobProg); # if first run fails, we come here \$restartCount = 0; while (1) { \$restartCount++; if (\$restartCount == 3) { print "Cannot restart any more... Exiting\n"; alert(\$jobName); exit(-1); } else { print "Exiting with code \$code\n"; print "Waiting for cleanup \n"; sleep(\$wait); print \$code . "... restarting \n"; \$code = system(\$jobProg); } } sub alert(\$){ my \$jobName = shift; my \$from = jobRunner@company.com; my \$to = admin@company.com; my \$subject = "Process \$jobName Failed"; \$smtp = Net::SMTP->new(mail.company.com); \$smtp->mail(\$from); \$smtp->to(\$to); \$smtp->data(); \$smtp->datasend("To: \$to\n"); \$smtp->datasend("Subject: \$subject\n"); \$smtp->datasend("Tried to restart \$jobName \$maxRestartCount times\n"); \$smtp->datasend("It Failed\n"); \$smtp->dataend(); \$smtp->quit; }

jobRunner.pl programnn seeneklerini komut satrndan perl jobRunner c .pl komutunu ileterek grebiliriz. Bu seeneklerin aklamas yledir: s o c c so maxRestartCount: jobRunner.plin balatm olduu ve kontrol ettii s s g g program oknce, en fazla ka sefer daha tekrar ayaa kaldrlmas gerektiini c u c g g kontrol eder. Eer bir program maxRestartCount kere km ise, jog co us bRunner.pl belirtilen admin kiisine bir e-mail ile durumu bildirecek, s 219

6. Sonuc Ortam ve programn maxRestartCount kere km olduunu haber verecektir. co us g Program bir daha balatlmayacaktr. s wait: Ckme ile tekrar balatlma arasnda ka saniye beklenmesi gerektiini o s c g belirler. jobname: Program balatan kiinin atad bir isim. Herhangi bir kelime s s g olabilir. s progname: Iletilecek programn balang komutu. JBoss rneinde bu s c o g sh run.sh olacaktr. Tm path (full path) burada belirtilir. u jobRunner.pl kontrolnde mesel JBoss balatmak iin tipik bir kullanm u a s c yle olabilir. so
perl jobRunner.pl 3 10 JBossServer1 sh /usr/local/jboss/bin/run.sh

Not: Bu ekilde altrdmz servis programn durdurmak iin, programn s c s g c kendisini deil, onu balatan ve idare eden jobRunner.pl programn ldrmemiz g s o u gerektiini unutmayalm. Balatc program grmek iin Unix uzerinde ps - g s o c eaf | grep perl ile alacamz listede, bu Perl scriptini kill -9 ile durdurag biliriz. Unix sre kontrol ve listelemesi iin 10.1.2 blmne bakabiliriz. u c u c ou u

6.2.2

Deamon Programlar

Apache gibi balang programlar kendini arka plana (background process) s c atan trden programlar iin, kontrol bir port bazl yapabilen idare bir scriptini u c u kullanmamz gerekiyor. Cunk kendini arka plana atan scriptler, balatc u s ardktan sonra hemen geri dnerler ve bu da jobRunner.pl gibi bir program c g o iin aldatc olacaktr (programn km olduunu zannedecektir). O zaman, c co us g kontrol edilen programn kp kmediini nplandan geri gelip gelmemek co u co g o deil, belli bir port uzerinde dinleyici olup olmadn anlayarak kontrol edebilg g iriz. Sistemde bir portun kullanlma durumunu netstat ile kontrol edebiliriz. netstat hakknda ayrntl detay iin 10.6 blmne bakabilirsiniz. c ou u Liste 6.4: deamonRunner.pl
#!/usr/bin/perl use Net::SMTP; \$argCount=\$#ARGV + 1; die "Usage: perl t.pl <maxRestartCount> <wait> " . "<port> <jobname> <progname>\n" if (\$argCount != 5); \$maxRestartCount = \$ARGV[0]; \$wait = \$ARGV[1];

220

UYGULAMA ISLEYISINI KONTROL ETMEK


\$port = \$ARGV[2]; \$jobName = \$ARGV[3]; \$jobProg = \$ARGV[4]; # if first run fails, we come here \$restartCount = 0; while (1) { if (\$restartCount == \$maxRestartCount) { print "Cannot restart any more... Exiting\n"; alert(\$jobName); exit(-1); } else { sleep(\$wait); print \$code . "... checking port \$port \n"; @netstatout = netstat -ano; foreach \$line(@netstatout) { @tokens = split(:|\s,\$line); if (\$tokens[7] =~ /\$port/) { \$found = 1; } } if (\$found != 1) { \$restartCount++; \$code = system(\$jobProg); } } } sub alert(\$){ my \$jobName = shift; my \$from = deamonRunner@company.com; my \$to = admin@company.com; my \$subject = "Process \$jobName Failed"; \$smtp = Net::SMTP->new(mail.company.com); \$smtp->mail(\$from); \$smtp->to(\$to); \$smtp->data(); \$smtp->datasend("To: \$to\n"); \$smtp->datasend("Subject: \$subject\n"); \$smtp->datasend("Tried to restart \$jobName \$maxRestartCount times\n"); \$smtp->datasend("It Failed\n"); \$smtp->dataend();

221

6. Sonuc Ortam

\$smtp->quit; }

deamonRunner.pl seenekleri jobRunner.pl ile neredeyse ayndr, tek fark, c belli aralklarla kontrol edilmesi gereken bir port parametresidir. Bu parametrenin uzerinde dinleyici olma durumu netstat -ano ile belli aralklarla kon trol eden script, eer o port dinlenmiyorsa, dinleyen programn ktun kabul g co ug u edilecek ve tekrar balatmak iin gerekli komutu uygulayacaktr. Tipik bir deas c monRunner.pl kullanm yledir: so
perl jobRunner.pl 3 10 80 Apache1 /usr/local/apache/bin/apachectl start

Bu komuta gre, Apache programnn varl port 80e baklarak her 10 saniyede o g bir kontrol edilecek, eer program km ise tekrar balatlacaktr. Bu tekrar g co us s balatma ilemi en fazla 3 kere tekrarlanacak, 3 kereden sonra tekrar balatmak s s s denenmeyecek, durum grevli admin kiisine bir e-mail ile bildirilecektir. o s

6.3

Uygulamadan Istatistik Almak

Srecimizin ileyi durumunu kontrol eden yukardaki scriptler sayesinde, eer u s s g izlenen bir sre km ise, onu tekrar balatarak sistemin devamn salamak u c co us s g s mmkn olacaktr. Ileyi hakknda daha detayl bilgiler istersek, bu bilgiu u s leri uygulama iinden paylamamz, bir ekilde d dnyaya ae etmemiz ve c s s s u s s belli aralklarla bu bilgileri gncellememiz gerekmektedir. Ileyi bilgilerini d u s s dnyaya ae edersek, bu bilgileri (tercihen) grsel bir idare program sayesinde u s o izleyebilir, bir ekranda gsterebilir, hatt ilgin olan artlar uzerinde alarm o a c s artlar tanmlamak suretiyle yetkili bir admin kiisinin (artlar ihll edildiinde) s s s a g e-mail ile bilgilendirilmesini salayabiliriz. g J2EE dnyasnda bir uygulamann i istatistiklerini paylamak ve idare u c s bilgilerini d dnyaya gstermek iin JMX teknolojisi kullanlr. JMX, Java s u o c Management EXtensions (Java Idare Uzantlar) cmlesinin ksaltlmdr. Bu u s teknoloji sayesinde bir uygulama, belli bir standarta uyan bir MBean classn (bir bean) d dnyaya gsterebilir. Aslnda JMX ile MBean ae etmek, datk s u o s g nesne teknolojisi ile nesnemizi JVM dndan eriime amaya ok benzer, ama s s c c iki fark (stnlk) vardr: Bir: JMX ile dardan balanan mteri, MBeanlerinizin u u u s g us metotlarn dinamik ekilde gezebilir. Iki: JMX teknolojisi, idare amal teknolos c jiler arasnda piyasada tutmu bir teknolojidir, bu yzden birok ticari ve ak s u c c yazlm urn istatistiklerini JMX uzerinde paylamak amacyla hazr MBeanler u s yazp urnlerine dahil etmilerdir. Bylece uygulamamz, bu hazr MBeanleri u s o olduklar gibi alp, kendi MBeanlerimiz ile beraber yanyana ae edebilir. His bernate org.hibernate.jmx.StatisticsService MBeani bu ekilde hazr s yazlm bir istatistik nesnesidir. s 222

UYGULAMADAN ISTATISTIK ALMAK

6.3.1

JMX ile MBean Yazmak

D dnyaya bilgi vermek iin, Kendi MBeanimizi yazmay renmemiz gerekiyor. s u c og Iki trl MBean stili vardr, statik MBean ve dinamik MBean. Statik MBean u u ile uygulama srasnda ismi deimeyecek parametreleri sunabiliriz. Mesel gs a uygulamamzn nbellek byklu, veri taban balant havuzundaki aktif o u u ug g balantlar, ya da sistemdeki aktif kullanc says gibi parametrelerin ne olduu g g nceden bilinen parametrelerdir, ve uygulama srasnda, ya da makinadan mako inaya deimezler. gs Dinamik MBeanler ise, ileyi annda ya da makinadan makinaya deiebilecek s s gs parametreleri ae etmek iin kullanlr. Mesel uygulamamzn uzerinde kotuu s c a s g makinann disklerinin kullanm luleri (IO read/write) gibi bir istatistik dio c namik MBean gerektirir, unk uygulamamz kurulduktan ve kullanma baladktan c u s sonra bir makinaya ek disk, ek ilemci gibi donanm uzantlar yapmak mmkndr; s u u u Eer istatistik paylama yntemimiz sabit disk isimleri uzerinden bilgi topluyor g s o (ve JMX ile paylayor) olsayd, yeni diskler eklendikten sonra bu ek birimler s d dnya tarafndan grlemez olacakt. s u ou Statik MBean Statik MBean tanmlamak iin sonu MBean ile biten bir interface, ve bu interc facei gerekletiren bir class gerekecektir. Ornek olarak, bir Web uygulamasna c s yaplan toplam ziyaretleri gsteren bir MBean yazalm: Esas deerleri tayan o g s saya, VisitCounter adl bir Singleton class olsun. c
public class VisitCounter { private static VisitCounter instance = null; private VisitCounter() { } public static VisitCounter instance() { if (instance == null) { instance = new VisitCounter(); } return instance; } public int visitCount = 0; public synchronized void incrementCount() { visitCount++; } public int getVisitCount() { return visitCount; } }

223

6. Sonuc Ortam Saya nesnesi uzerinde arttrma ilemini aran bir Web ltresi olacaktr. c s c g Ayrca Java Servlet belirtimine (specication) gre bir Filtre, Web istei balamadan o g s nce ve sonra iletilebilen bir kod parasdr. Biz ltremizi her *.do ars iin o s c c g c aktif olacak ekilde ayarlayalm. s Liste 6.5: VisitCounterFilter.java
public class VisitCounterFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); VisitCounter.instance().incrementCount(); } public void destroy() { } }

Liste 6.6: web.xml


<filter> <filter-name>VisitCounterFilter</filter-name> <filter-class> org.mycompany.kitapdemo.util.VisitCounterFilter </filter-class> </filter> <filter-mapping> <filter-name>VisitCounterFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping>

Saya deerlerini d dnyaya gstermek iin, JMX uzerinden kullanabileceimiz c g s u o c g bir statik MBean yazalm.
public interface UserStatMBean { public int getTotalRequestCount(); } public class UserStat implements UserStatMBean { VisitCounter counter = null;

224

UYGULAMADAN ISTATISTIK ALMAK


public UserStat() { counter = VisitCounter.instance(); } public int getTotalRequestCount() { return counter.getVisitCount(); } }

Bu MBeani bir MBeanServerMBeanServer ile kayt ettirdiimiz zaman, d g s dnya totalRequestCount adl istatistii grebilecektir. MBean kayt ettirmek u g o iin, projenin balang kodlar ilettii yerde (Web uygulamalar iin Appc s c s g c Startup class) u ekilde kodlar iletmemiz gerekir. s s s
public class AppStartup implements AppStartupMBean { public void start() throws Exception { ... MBeanServer mbeanServer = (MBeanServer) MBeanServerFactory.findMBeanServer(null).get(0); LocateRegistry.createRegistry(new Integer(jmxPort).intValue()); UserStat userStat = new UserStat(); ObjectName userStatName = new ObjectName("UserStat:type=UserStat"); mbeanServer.registerMBean(userStat, userStatName); ... } }

Car findMBeanServer ile JBossun MBeanServerna erimi oluyoruz. Bu g s s server, MBeanlerin kayt edildii ve merkezi bir giri noktas salayan noktadr. g s g Eer yeni bir MBeanServer yaratmak istesek, g
MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();

kullanrdk. Metot findMBeanServer kullanmakla, JBossun iinde olan tm c u dier MBeanlerin de kayt edilii merkezi noktay alm oluyoruz. g g s JBossun kontrol ettii MBeanleri grmek iin, taraycnzdan /jmx-cong o c sole adresine gidebilirsiniz. Sekil 6.1 uzerinde grldu gibi UserStat adl o u ug yeni MBeanimiz dier MBeanler yannda servise eklenmitir. MBean balantsnn g s g uzerine tklayarak iindeki e (attribute) deerlerini grebiliriz. c og g o Dinamik MBean g Oeleri deiken yapda olan MBean yazmak iin, statik MBean teknolojisini gs c kullanamayz. Burada dinamik MBeanler imdadmza yetiiyor. Dinamik MBean s yazmak iin genellikle kullanlan dzen (pattern), deiken eleri, eklenip c u gs og karmasna izin verdii ve anahtar bazl veri tutabildii iin bir HashMap uzerinde c g g c s tutmaktr. Ilem annda e olmas istenen deerler, dinamik bir ekilde HashMape og g s anahtar olarak verilir. 225

6. Sonuc Ortam Bu HashMapi JMX uzerinden d dnyaya gstermek iin, MBean iinde s u o c c annda bir dnum yapmamz gerekmektedir. Bu dnum, HashMap anahtar o us o us (key) deerini MBean e ismine, HashMap deerini ise MBean e deeri hline g og g og g a getirmelidir. Bu dnum rneini StrutsHibPerformance projesi altndaki o us o g org.mycompany.kitapdemo.service.OsStatistics MBean class uzerinde gryoruz. ou Bu kodda, HashMap uzerinden dinamik MBean yaratmak iin kullanlan c kod paras (dinamik ksm commentleri altnda listelenen blm) olduka c ou c basmakalp kodlardr. Bu kodlar, dinamiklik eklemek istediimiz dier bir g g MBeane olduu gibi ekleyebilir, ya da tekrar kullanm (reusability) arttrmak g amacyla, dinamiklik kodlarn bir ust class iinde tutup MBeanimizden miras c alabiliriz. OsStatistics classnn ihtiyac olan deerler, iletim sisteminde gelmekg s tedir. Bu deerler mikroilemci kullanm yzdeleri, ne kadar bo bellek olduu g s u s g gibi iletim sisteminin takip ettii bilgilerdir, ve komut satrnda bunlar grmek s g o iin vmstat komutunu kullanyoruz. OsStatistics, vmstatin ktsna erimek c c s iin Runtime.getRuntime().exec() metotu ile vmstati iletmekte, ve geri gec s len metin bazl kty tarayarak iinden ilgilendii deerleri ekip karmaktadr. c c g g c c vmstat hakknda detaylar 5.3.2 blmnde bulabilirsiniz. ou u Dinamik MBeanimiz JBossa gnderildikten ve ilk deerlerini topladktan o g

Sekil 6.1: UserStat MBeani JmxConsoleda 226

UYGULAMADAN ISTATISTIK ALMAK sonra, /jmx-console ekranndan Sekil 6.2 uzerindeki gibi gzkecektir. o u

Sekil 6.2: Dinamik MBean Ekran Grldgu gibi, mem_cache, mem_swpd gibi deerler, direk vmstat ktsndan o u u g c gelmektedir. mem_swpd, swpd esinin bana mem_ eklenmek suretiyle yaratlmtr. og s s g Oelerin bana mem eklenmesinin sebebi, ileride OsStatistics MBeanine ios stat gibi bir Unix komutunun ktsn da eklersek, parametrelerin birbirine c karmamas iindir. s c OsStatistics kodlarnda belli aralklarla istatistik deerlerinin gncelleng u mesi iin OsStatistics iinde olan bir Thread mevcuttur. Bu Threadi Osc c Statictics nesnesini kayt ettiimizde balatmamz gerekir. Bunun iin uygug s c lama balang kodlar iinde (StrutsHibPerformance projesi iin AppStartup) s c c c osStatistics.startThread() metotunu armamz yeterlidir. Balang kodc g s c larnn tamam oyle gzkr. s o u u
mbeanServer = ... OsStatistics stats = new OsStatistics(); stats.startThread(); ObjectName name = new ObjectName("OsStatistics:type=OsStatistics"); mbeanServer.registerMBean(stats, name);

Istatistik deerlerinde, alnma stili olarak UserStat ile OsStatistics arasnda g bir fark vardr. UserStat, kendine yaplan tm get arlarn baka bir merkezi u c g s nesneye aktararak (delegate) gerek deerlerin o baka yerde gncellenmesini c g s u bekliyordu. OsStatistics ise, kendi deerlerini kendi toplamakta, kendi ilemekte g s ve kendi muhafaza etmektedir. Bu fark, iki deiik MBean gncelleme yntemgs u o ini sahneye kartmas iin byle hazrlanmtr, ve MBeanlerin dinamiklii c c o s g 227

6. Sonuc Ortam ya da statiklii ile bir alkas yoktur. Statik bir MBean uzerinde de deerleri g a g toplayan, ileyen ve muhafaza eden kodlar yazabilirsiniz. s Hazr yazlm ak yazlm ya da ticari paketlerin MBeanlerini paylamak s c s iin o paketlerin belgelerine baknz. Mesel Hibernate belgelerinde Hibernate c a istatistik MBeanini paylamak iin unlarn yaplmas sylenmitir. s c s o s
mbeanServer = .... Hashtable tb = new Hashtable(); tb.put("type", "statistics"); tb.put("sessionFactory", "kitapdemo"); ObjectName on = new ObjectName("hibernate", tb); StatisticsService hibstats = new StatisticsService(); hibstats.setSessionFactory(HibernateSession.getSessionFactory()); mbeanServer.registerMBean(hibstats, on);

Tm bu paylasmlar yapan rnek AppStartup kodlarn, StrutsHibPerforu o mance projesinde bulabilirsiniz.

6.3.2

JmxMonitor

MBean deerlerini jmx-console uzerinden gstermek bir yararl bir gzlem g o o yntemidir. Fakat gerek dnyada ilemekte olan bir sistemde, bize sunulan o c u s istatistiklere sadece plak gzle bakmaktan daha fazla yeteneklere ihtiyacmz c o vardr. Dunelim ki, OsStatisticsden gelen makinamnn kullanlmayan bellek us kapasitesi (mem_free) belli bir deer altna derse, haberimizin olmasn isg us tiyoruz. Ya da, statik MBean rnei olarak yazdmz UserStat nesnesindeki o g g totalRequestCount, belli bir deeri getiinde bir alarm durumu olmal ve adg c g min e-mail ile haberdar edilmelidir. Bu tr izleme ilemlerini nasl yapacaz? u s g JmxMonitor1 ak yazlm projesi, bu tr ihtiyalar karlamak iin yazlmtr. c u c s c s Eer bir uygulamada ae edilmi MBeanler var ise, bu MBeanler uzerindeki g s s her e iin, JmxMonitorde bu eyi gzleyen, ve kullancnn tanmlad bir og c og o g ve ya daha fazla eik deerini (threshold) ya da eitlik artlarna uyan dus g s s rumlar uzerinde bir alarm art tanmlayabiliriz. Alarm artlar ortaya karsa s s c JmxMonitor e-mail ve HTML nyzden durumu admine bildirilecektir (Jmxo u Monitor kullancsnn admin grevlisi olduunu farz ediyoruz). o g JmxMonitor kodlar iine hibir MBean isminin gmlmesi (hardcode) gerekc c o u mez. JmxMonitor, JMX teknolojisinin Java Reection benzeri dinamik keif s zelliini kullanarak, nce bir MBeanServer uzerindeki tm MBeanleri alr o g o u daha sonra bu MBeanlerin tm gelerini dinamik olarak kefeder. MBean ve u o s e listesi kullancya sunulur ve kullanc, elerin arasndan ilgilendiklerini og og seerek uzerlerinde eik ya da eitlik artlar tanmlar. c s s s Bu potansiyel alarm artlar ana ekran uzerinde listelenir, ve ileri bir zas manda, eer uyan bir eitlik ya da geilen bir eik art olursa, ana ekranda bu g s c s s alarm yanp snmeye balayacaktr. Ayrca admine e-mail ile durum bildirilir. o s
1 http://jmxmonitor.sourceforge.net

228

UYGULAMADAN ISTATISTIK ALMAK JmxMonitor Web bazl bir uygulamadr. Web uygulamasnn iinden (Jmxc MonitorStartup) balatlan ve alarm deerlerini kontrol eden bir Thread, belli s g aralklarla srekli kontrol yapyor olacaktor . Ayrca JmxMonitor Adaptor u dzenini (pattern) kullanarak, istatistik toplamak iin kulland balant teknolou c g g jisini deitirmesi de mmkndr. Mesel paket iinden kan adaptr Jmxgs u u u a c c o FacadeJdk15 classdr, fakat JmxMonitoru uzatmak isteyen bir programc, soket uzerinden bilgi toplayan bir adaptr yazabilir. Bu socket adaptr, servis o ou tarafndan yine socket uzerinden bilgi ae eden bir makina, port ikilisine s balanacak, ve bekledii formattaki deerleri alarak admine eik ve eitlik g g g s s seimi iin sunacaktr. Kendi yazdnz (custom) adaptrn JmxFacade interc c g ou faceini gerekletirmesi gerekmektedir. Buna gre her adaptrn; c s o ou 1. Verilen makina ve port ikilisine balanmas mmkn olmaldr (connect) g u u 2. Istatistik sunan servisteki tm ana birimler ve bu birimler alt birimu lerinin listesi alnabilir olmaldr (retrieveAllObjectNames) 3. Her lumn gerek deerini almak mmkn olmaldr getLatesto c u c g u u Value) Altta bir adaptrn sahip olmas gereken metotlar gzkmektedir. Her adaptre ou o u o uymayan (stteki metotlar haricinde) metotlardan bazlar, artlara gre bo u s o s braklabilir.
public interface JmxFacade { public Machine getMachine(); public void connect(Machine machine) .. public Map retrieveAllObjectNames() .. public String getLatestValue(ObjectName name, String attribute) .. public void refreshValues() .. }

Servis Taraf JmxMonitorun JmxFacadeAdaptor15 adaptr ile bir MBeanServera eriebilmesi ou s iin, o servisin JMX MBeanlerini RMI uzerinden sunmas gerekir. MX4J paketi c bu tr bir RMI kprsn sunmaktadr. Kullanmak iin AppStartup iinde u o uu u c c bulduumuz ya da yenisini yarattmz MBeanServer uzerinde bu kprnn g g o u u nasl kullanlacan belirtmemiz gerekecektir. g
public class AppStartup implements AppStartupMBean { public void start() throws Exception { ... mbeanServer = ... // MBeanServer al ya da yarat ... final String localRmiRegistryHost = "localhost"; final String localRmiRegistryPort = "42004";

229

6. Sonuc Ortam
final String jmxHost = "localhost"; final String jmxPort = "44334"; final String jmxUrl = "/kitapdemo"; JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://" + localRmiRegistryHost + ":" + localRmiRegistryPort + "/jndi/rmi://" + jmxHost + ":" + jmxPort + jmxUrl); (JMXConnectorServerFactory. newJMXConnectorServer(url,null,mbeanServer)).start(); ... ...

Bu balatm komutu ile bizim atadmz bir RMI URLi olan bir JMX servisi s g yaratm oluyoruz. Uzaktan balanmak isteyenler JMX RMI arsn yle bir s g c g so URLi oluturarak gerekletireceklerdir: s c s
service:jmx:rmi://localhost:42004/jndi/rmi://localhost:44334/kitapdemo

Bu URLin ileyip ilemediini anlamak iin en abuk test udur: JDK 1.5 s s g c c s iinde paketten kan JConsole adnda bir uygulama mevcuttur. Bu uygulama, c c ayn JmxMonitor gibi RMI uzerinden dinamik olarak MBeanleri kefeder ve s gsterir (fakat JmxMonitor gibi alarm artlar koymanza izin vermez). Bu o s uygulamay JDK_1_5/bin/jconsole komutunu kullanarak balatabiliriz. Ilk s kan balant diyalog kutusunda, Advanced tabine giderek, ustte grlen c g ou URLi (tabii servisimizi de balattktan sonra) gireriz. Sekil 6.3 uzerindeki ekran s grlecektir. ou Dikkat edersek, uygulamamzdan ae ettiimiz UserStat, OsStatistics s g ve Hibernate istatikleri dinamik olarak kefedilmi ve listelenmitir. s s s 230

UYGULAMADAN ISTATISTIK ALMAK JmxMonitor Kurmak JmxMonitor, altyap olarak kitabmzda sunulan StrutsHibxx projeleri ile ayn teknik mimariye sahiptir. Bu sebeple indirmesi, kurulmas iin yaplmas gerekenc ler, A.1.2 blmndekiler ile ayndr. Ek olarak, balang verilerini yklemek ou u s c u iin JMXMONITOR/src/sql/init_data.sql scriptini MySQL (ya da dier) veri c g tabannz uzerinde iletmeniz gereklidir. s Bundan sonra, JBoss servisinizi balatn ve localhost:8080/jmxmonitor s adresini ziyaret edin. JmxMonitor ile bir MBeanServera balanmak iin, o g c servisin makina ismi ve port numarasna girmemiz gerekiyor. Bu alanlar iin c rnek baz deerler Sekil 6.4 uzerindeki gibi gzkecektir. o g o u Alanlar iin girilmesi gereken deerleri yle bulmamz gerekir: Bir MBeanServera c g so bir RMI kprs uyguladmzda (daha nce AppStartup iinde rneini gsterdiimiz o uu g o c o g o g gibi), u parametreleri kullanmtk s s
final final final final final String String String String String localRmiRegistryHost = "localhost"; localRmiRegistryPort = "42004"; jmxHost = "localhost"; jmxPort = "44334"; jmxUrl = "/kitapdemo";

Bu parametrelerden jmxUrl, JmxMonitorn URL alanna, jmxPort, port alanna, u jmxHostun ise host alanna girilmesi gerekmektedir. Bu deerleri girip, Add g Machine dmesine tklarsak, JmxMonitor bu servisi listesine ekleyecektir (Sekil ug 6.5). Listelenen bir servis uzerine tklarsak, JmxMonitor servise RMI uzerinden balanmaya alacak, ve bir sonraki ekranda (Sekil 6.6) bu servisin tm MBeanlerinin g c s u listesini bize sunacaktr.

Sekil 6.3: JConsole 231

6. Sonuc Ortam

Sekil 6.4: Giri Ekran s

Sekil 6.5: Servis Eklendi

232

UYGULAMADAN ISTATISTIK ALMAK Ayn JConsole rneinde olduu gibi, kendi yazm olduumuz MBeanleri o g g s g de bu ekranda grmemiz mmkndr. Bu MBeanlerden biri iin bir alarm art o u u u c s tanmlamak iin, mesel OsStatistics MBeaninindeki bir e iin, ilk nce c a og c o g elerin listesini grmemiz gerekiyor. Oe listesini almak iin OsStatistics og o c balantsn tklamamz lzm. g a Sekil 6.7 uzerinde tklamadan sonra tm eleri gryoruz. Bu elerden u og ou og biri ustnde bir alarm art yaratmak istersek, enin uzerindke tklamamz u s og gerekecek. Ornek olarak OsStatistics altndaki mem_free esi uzerinde alarm og yaratalm, tklamadan sonra, Sekil 6.8 uzerindeki ekran grrz. ouu Bu ekranda alarmn mem_free gerek deeri 640000 altnda derse, bir c g us alarm olumasn istiyoruz. O zaman Comparator yni karlatrc olarak < s a s s iaretini seeriz, ve deer olarak 640000 deerini Threshold yni eik deeri s c g g a s g kutusuna gireriz. Alarm eklendikten sonra Sekil 6.9 uzerinde grulen ekrana o geliriz. Eklenmi alarm silmek iin, alarmn yanndaki Delete balantsna s c g tklayabilirsiniz. Bu ekilde devam ederek birden fazla alarm eklememiz mmkndr. Alarm s u u u eklememiz bitince, ana sayfaya dnebiliriz. Ana sayfaya dnnce eklediimiz o o u g alarmlarn sayfann altnda listelendiini greceiz (Sekil 6.10). g o g Artk yapmamz gereken tek ilem, izlemekte olduumuz makina ve port s g ikilisi uzerinde yaplacak izleme/gzetlemeyi ilemini aktif hle getirmektir. o s a Bylece JmxMonitor, uzerinde alarm olan elerin en son deerlerini periyo og g odik bir ekilde alarak, eik veya eitlik artlarna uyup uyulmadn kons s s s g trol edebilecektir. Gzetlemeyi aktif hle getirmek iin, makina ve port ikilisi o a c

Sekil 6.6: MBean Listesi 233

6. Sonuc Ortam

c g Sekil 6.7: MBean Iindeki Oeler

Sekil 6.8: Alarm Ekleme Ekran

234

UYGULAMADAN ISTATISTIK ALMAK

Sekil 6.9: Alarm Eklendi

Sekil 6.10: Ana Sayfaya Dn - Alarm Gsteriliyor o us o

235

6. Sonuc Ortam yanndaki Active seeneine tklarz. Aktif hle getirdiimiz birimin iareti, c g a g s yeile dnecektir (Sekil 6.11); Bu renk, o makina ve portun izlenmeye baladna s o s g bir iarettir. Eer izlemeyi durdurmak istiyorsak, DeActivate seeneini kuls g c g lanabiliriz.

Sekil 6.11: Aktif Olan bir Makina/Port Ikilisi

236

Bl m 7 ou

Test Etmek

Bu Bl mdekiler ou JUnit ile birim testleri JMeter ile kabul testleri jMock

237

7. Test Etmek rogramlama srasnda, uzerinde altmz kodu arada srada iletebilmek c s g s iin kodu derleme ileminden geirmemiz gerekir. Derleme ilemini grevc s c s o lerinden biri iler kod uretmektir, ve ok nemli dier bir grevi ise tm s c o g o u kodlar uzerinde szdizim kontrol yapmaktr. Mesel gl tipleme (strong typ o u a uc u ing) bekleyen bir dil kullanyorsak, bir eitliin (=) iki tarafndaki iki deikenin s g gs tiplerinin birbiri ile ayn olmas gerekecektir. Bu, bize dil tarafndan verilen bir kontroldr, ve yapabileceimiz potansiyel bir hata iin hatrlatc nitelik tar. u g c s Dil tarafndan getirilmi bu ekildeki kurallar, programmzn doruluu iin s s g g c getirilmi tecrbeye dayal kurallarn toplamdr. Bu kurallar nasl konulmutur? s u s Eer istatistiki olarak bir tipteki deikenin tekine eitlenmesi programc tarafndan g gs o s ok yaplan bir hata ise, bu hatay ngren bir kural, programmz eitleme c o o s hatalarndan kurtarm olur. Alternatif olarak zayf tipli (weakly typed) diller s her tipi, her dier tipe eitlemeye izin verip, programcya sormadan tip deiimini g s gs ileyi annda yaparlar. Bu dillerin kullanm beklentileri ona gredir. s s o Derleme aamas szdizim hatalarn kontrol eder; Fakat bu kontrollerden s o geen kodumuz, tm hatalar arnm mdr? Bu soruya cevap doal olarak c u s g Hayr olacaktr. Programclk ile uraan herkesin bildii gibi, szdizimsel g s g o kurallar potansiyel hatalar bulmakta yardmc olsalar da, programn iinde c mantk hatalar (bug) olmas hla muhtemeldir. Htta, yine istatiksel olarak a a diyebiliriz ki, etrellik seviyesi orta ve ust seviyede olan hibir program ilk c u c dzgn derlenmesinden sonra beklendii gibi almayacaktr. Unutkan olan u u g c s insanlar (Kural #4), muhakkak program yazarken mantk hatas yaparlar. O zaman programmz yazarken, aynen szdizimsel hatalar derleyiciye o yakalattrdmz gibi, mantk hatalarn da yakalayabilecek olan kendi kong trol edici kurallarmz kendi uzerimizde yaratmamz gereklidir. Fakat bu kon trollerin tip kontrolleri gibi szdizimsel seviyede deil, programn ileyii seo g s s viyesinde olmas gerekecektir. Program ileyiini kontrol etmek istiyorsak, programmz iletmemiz ve s s s sonucunu kontrol etmemiz gerekecektir. Bu ileyiin nemli faktrlerinden biri s s o o otomatik yaplabilmesi olmaldr unk otomatik yaplabilen kontroller, birden c u fazla ve sra hlinde kodun uzerinde iletilebilirler. a s Bu tr otomatik ileyi kontrollerini iki seviyede gerekletirmemiz mmkndr: u s s c s u u u Birincisi en ufak kod birimi (modl) baznda, ikincisi ise programn geneli, yni u a programn d kullanl baznda olacaktr. Bu iki kontrol yntemini nasl kus s u o racamz ve kullanabileceimizi alttaki blmlerde greceiz. g g ou o g

7.1

Birim Testleri

Birim testleri bir fonksiyon ya da metot seviyesinde yaplr. Birim testleri isimlerini, en ufak iler kod birimi olan fonksiyonu test ediyor olmalarndan s alrlar. Birim testinin kullanm olduka basittir: Normal program ileyii srasnda c s s bir bir metot ya da fonksiyonu test etmek istiyorsak, o metotu ieren nesneyi c 238

BIRIM TESTLERI new ile yaratrz, ve sadece test etmek istediimiz metotu arrz. Mesel elimg c g a izde iki sayy toplayan add adl bir metot olsun.
public class AdderService { public int add(int x, int y) { return x+y; } }

Bu class test etmek iin, bir main ilevden bu class yle kullanrz (aslnda c s so tavsiye ettiimiz test arc nokta main deildir, fakat imdilik -kurmas ok g c g g s c basit olmas sebebiyle- rnee bu ekilde balamak istedik) o g s s
public static void main(String[] args) throws Exception { AdderService service = new AdderService(); if (service.add(2, 2) != 4) { System.out.println(test failed); System.exit(-1); } }

Bu testi komut satrndan ardmzda, eer fonksiyon doru yazlmsa hibir c g g g g s c hata mesaj grmememiz gerekir. Birim testlerinin amac budur: Belli deerleri o g ilem mantna girdi olarak verince, beklediimiz kt deerlerinin verilip vers g g c g ilmediini ilem annda (runtime) kontrol etmek, verilmediyse hata raporu vereg s bilmek. Ustte verilen fonksiyon ve test ok basit rneklerdir, fakat orta ve c o daha ust etrellikte olan bir fonksiyonu da ayn yntemle test edebiliriz, ve uc o bu gibi testlerden birounu otomatik olarak ilem kodu uzerinde arka arkaya c g s iletebiliriz. s

7.1.1

s JUnit - Birim Test Iletici

Eer birden fazla birim testi arabilmek ve daha iyi karlatrc foknsiyonlar g c g s s kullanmak istiyorsak, JUnit1 projesinin test altyapsn kullanabiliriz. JUnit, Birim testlerinizi main yerine, test edici zel classlar iinden armamz o c c g salar. g Ozel test edici classda ismi test ile balayan her metotu, JUnit otomatik s olarak arabilir (bylece main iinden (elle) her ary eklememiz gerekc g o c c g mez) assertEquals, assertTrue gibi karlatrc fonksiyonlar salayarak, bass s g makalp if arlarndan bizi kurtarr c g
1 http://www.junit.org

239

7. Test Etmek Bu altyapnn ustne, tarafmzdan, sonu Test.class ile biten her classn u da birim test classi kabul edilip, iletilmesini salayan AllTest adl bir global s g iletici yazlmtr. Bu global iletici, sonu Test.class ile biten tm dosyalar s s s u CLASSPATHten toplayarak JUniti arabilir ve birim testlerin iletilmesini ve c g s sonularn toplanmasn salayabilir. AllTest yardmc kodu Ant build.xml c g iinden arlabilir. Ornek kitap kodlarmzdaki her proje iindeki build.xml c c g c iinde bu tr bir test targeti bulabilirsiniz. Kullanm yledir: c u so
... <target name="test" depends="clean,compile"> <java fork="yes" classname="org.mycompany.kitapdemo.util.AllTest" taskname="junit" failonerror="true"> <arg value="Test.class"/> <classpath refid="compile.classpath"/> </java> </target> ...

Bu build.xml blouna gre, nce clean ve compile targetleri iletilerek eski g o o s iler kodlar silinip kaynak kodlar derlenecek, sonra AllTest class, Test.class s parametresi ile arlacaktr. c g Test.class yerine deiik bir sonekle biten birim test classlarn armak gs c g istiyorsaniz, <arg value ..> iin deiik bir deer verebilirsiniz. Simdi rnek c gs g o bir JUnit birim testini grebiliriz. o
import junit.framework.TestCase; public class AdderServiceTest extends TestCase { public void testAdd() { AdderService service = new AdderService(); assertEquals(5, service.add(3, 2)); } }

Testleri iletmek iin komut satrnda ant test yazmanz yeterlidir. Bunun s c sonuc olarak yle bir kt greceksiniz: so c o
... ... test: Adding org.mycompany.kitapdemo.sample.AdderServiceTest Adding org.mycompany.kitapdemo.util.AllTest\$Test ... Time: 3.835 OK (3 tests)

240

BIRIM TESTLERI Testlerimiz ilemi, kodlarn doru ilediini bulmu ve sonucu bildirmitir. s s g s g s s Eer kodlarda bir yanllk olsayd (mesel + iareti yerine yanllkla bir g s a s s iareti konmu olsa), s s
public class AdderService { public int add(int x, int y) { return x +- y; // yanl kod! s } }

o zaman test yle bir hata yakalayacakt: so


.. .. There was 1 failure: 1) testAdd(org.mycompany.kitapdemo.sample.AdderServiceTest)junit.fram ework.AssertionFailedError: expected:<5> but was:<1> at org.mycompany.kitapdemo.sample.AdderServiceTest.testAdd(Ad derServiceTest.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAcc essorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingM ethodAccessorImpl.java:25) at org.mycompany.kitapdemo.util.AllTest.main(AllTest.java:86) FAILURES!!! Tests run: 4, Failures: 1, Errors: 0 ...

Sonuca bakarsak, expected:<5> but was:<1> mesajnn verildiini gryoruz, g ou yni JUnit bize birim testimizin sonu olarak 5 beklediini, ama test edilen bira c g imden 1 deerinin geldiini sylemektedir. Bu hatal bir durumdur, beklenen ve g g o gelen deeri karlatran JUnit, bir uyumsuzluk olduunu grnce, hatal bir g s s g ou kod olduunu anlamtr, ve ok detayl bir tarif vermitir. Bu detayl trif asg s c s a sertEquals kullanm sayesinde gelmitir. Hatann sebebi ise, yanllkla koda s s koyulmu +- ileminin toplama deil, kartma yapmasdr! s s g c

7.1.2

Kurumsal Kodlar Birim Testinden Geirmek c

AdderService.add() islemi, dardan olduka izole bir ilem kodudur. Bu s c s metot uzerinde test gerekletirmek bu sebeble olduka kolayd. Fakat bir ku c s c rumsal uygulamalann ilemesi iin yazlan kodlarn, genellikle bir birletirici s c s (integrator) zellii vardr; Sektrmzde, ii sadece kurumsal uygulama yazo g ou u s mak olan irketlere bu sebeple sistem birletiricisi (system integrator) ismi s s verilir. Kurumsal bir uygulama, ok nadiren bir ada olarak tek bana i yapc s s maktadr. Ya bir veri tabanna balanrz, ya bir e-mail server uzerinde e-mail g 241

7. Test Etmek atarz, ya da eski (legacy) bir sisteme balanarak bilgi alverii yapmamz g s s gerekir. Bu iletiim gereklilikleri, doal olarak ilem mant kodlarmzn iine kadar s g s g c nfuz eder. Bunun kod bakm asndan bir sakncas yoktur. Sadece test edu c erken, d bir sistemle iletiim gerekliliklerinden dolay birim testinden geirmek s s c iin ardnz kod paracklar, bir birim test ortam iinde ilediklerinden c c g g c c s habersiz o d sisteme balanabilmeye alacaklardr. Ve bunda baarsz olas g c s s caklardr, unk sonuta, iinde ilem yaptmz ortam bir test ortamdr. c u c c s g Gerekli olan tm d servisler byk bir ihtimalle daha balatlmamtr, ve zau s u u s s ten balatlmalarnn da beklenmemesi gerekir: Bir birim testinden beklediimiz, s g komut satrndan, hibir d sisteme ihtiya duymadan programn etrel mantn c s c c g (onu agr bunu ar mantn deil) test edip bize sonucu bildirmesidir. c c g g g O zaman kurumsal uygulamalar nasl edeceiz? Kurumsal uygulamalar bir g ada deildir, ama birim testler uygulamann bir ada olmasn ister. O zaman g ada olmayan kodlar ada hline getirmenin tekniklerini renmemiz gerekiyor. a og Bir Nesneyi Taklit Etmek Taklit etmek (mocking), kurumsal uygulamalar birim testinden geirebilmek c iin ihtiyacmz olan tekniktir. Bir birim testinin ard ilem kodlarnn c c g g s balanmak istedii d sistemin yerine taklitini koyarsak ve o taklit nesneye g g s istediimiz (o test senaryosu iin gereken) verileri verdirebilirsek, ilem kodg c s larmz hibir eyden habersiz ileyip geri dnebileceklerdir. Birim testleri de c s s o bylece istedikleri ilem mantn test edebilmi olacaklardr. Yni birim testo s g s a lerinin ilemesi iin, d sistem nesneleri, taklit edilmelidir. s c s Taklitlemeyi, her d sistem iin deiik bir ekilde yapacaz (taklitlemeden s c gs s g muhaf tutacamz tek d sistem veri taban olacak, bunun sebeplerini 7.1.3 g s blmnde okuyabilirsiniz). ou u Socket, vs gibi d sistemlere ve ya APIlar ran kodlar s cag iin: jMock aracl ile bir nesnenin yerine metotlarnn ii boaltlm c g c s s ve sadece bizim istediimiz cevaplar dndren bir Java taklit nesnesi g o u koymak mmkndr. u u u Dier: Bu tr artlar daha etrel taklitleme gerektirebilir, ve elle kodg u s c lama isteyebilirler. O zaman, d sisteme balanan o nesneden miras s g alp (extend), metotlarnn iine testimizin bekledii cevaplar verecek c g kodlar koyarz. Bu, jMock ktphanesinin otomatik, perde arkasnda uu yaptnn perde nnde olan karldr. g o u s g jMock ile istediimiz herhangi bir nesnenin yerine onun taklidini koyag bilir, ve bu taklidin metotlarna dinamik olarak istediimiz cevaplar verdig rebiliriz. jMock, arka planda CGLIB adnda baytkod uretmeyi salayan bir g ara kullanmaktadr. CGLIB sayesinde jMock, mesel dn deeri bir String c a o us g 242

BIRIM TESTLERI olarak tanmlanan metot ismi ve onun beklediimiz dn deerlerini dig o us g namik olarak, sanki esas taklit edilen nesneden geliyormu gibi, ilem annda s s uretebilmektedir. jMock kullanmn bir rnek uzerinde grelim. Alttaki kodlar iinde Socketo o c Client adl bir nesne gryoruz. Bu nesne, Internetteki bir makina ve o makou inadaki porta bir Socket amaktadr. Bu makinann nerede olduuna dikkat c g edelim. Evet, Japonyada! Simdi, bu SocketClient kullanan ilem mant s g koduna gelelim. Bu classn ismi de (uygun olarak) AppLogic, ve yapt da g SocketClient uzerinden Japonyaya balanp oradan ald Japonca bilgileri g g Trkeye tercme etmek. u c u
public class SocketClient { public String takeWordFromJapan(){ String inputLine = ""; try{ Socket socket = new Socket("www.japan.jp", 5555); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader (socket.getInputStream())); out.println("DOMO ARIGATO!!! "); while ((inputLine = in.readLine()) != null) { out.println(inputLine); } out.close(); in.close(); socket.close(); } catch(IOException e){ e.printStackTrace(); } return inputLine; } } public class AppLogic { SocketClient client = new SocketClient(); public void setSocketClient(SocketClient client) {

243

7. Test Etmek
this.client = client; } public String translate() { String message = client.takeWordFromJapan() ; if (message.equals("HAI")) { return "evet"; } else if (message.equals("DOZO")) { return "lutfen"; } else if (message.equals("CAMPARE")) { return "??"; } return ""; } }

Bizim amacmz, AppLogic nesnesini test etmektir. O zaman AppLogic kodlarn dardan izole olmu bir ada hline getirmemiz gerekiyor. AppLogic kods s a larna bakarsak, test ettiimiz mantn translate metotu iindeki if komug g c tunun olduunu gryoruz. Demek ki, SocketClient yerine bir taklidini kog ou yarsak, kodlarmz d dnyadan izole etmi olacaz, ve bu taklide testimiz s u s g iinde istediimiz Japonca kelimeyi sylettirebilirsek, bu senaryonun gerekc g o tirdii translate metotunu test edebilmi olacaz. Ite jMock burada sahneye g s g s giriyor. jMock kullanan bir test aadaki gibi olacaktr. s g
1 2 3 4 5 6 7 8 9 10 11 12 13 14

public class TranslateTest extends MockObjectTestCase { public void testHai() { Mock mockObj = mock(SocketClient.class); AppLogic logic = new AppLogic(); logic.setSocketClient((SocketClient)mockObj.proxy()); mockObj.expects(atLeastOnce()). method("takeWordFromJapan") .will(returnValue("HAI"));

244

BIRIM TESTLERI
15 16 17 18 19

String answer = logic.translate(); assertEquals("evet", answer); } }

#5te SocketClient nesnesinin taklit tanmn yapyoruz. #7de test edeceimiz g AppLogic nesnesini yaratyoruz, ve taklit nesnesinin kendisi #9da yaratp AppLogic uzerinde set ediyoruz. Bu numaraya dikkat! Eer AppLogic ihtiyac olan g SocketClient nesnesini translate metotu iinde kendisi yaratyor olsayd, c biz bu ekilde taklide dayal bir testi yapamazdk. Cunk ilem kodlar bizim s u s verdiimiz taklit d nesnesi yerine, kendi yaratt ve Japonyaya balanmaya g s g g alacak esas nesneyi kullanrd. O zaman, ilem kodlarmzn d nesneleri her c s s s zaman dsardan, bir set aracl ile almas gerekmektedir. g Taklit nesnesine belli cevaplar verdirmek iin ise, jMockun expects, method c returnValue komutlarn kullanacaz. Bu zellikler jMock teknolojisinin en g o gcl tarafn tekil etmektedir, dinamik, String ile tanmladmz metot isimu u s g leri ve dn deerlerini arka planda baytkod hline gelip, JVM tarafndan o us g a annda ileme konulmaktadr! Ustteki rnekte, #11. satrda taklit nesnesine s o beklenen (ve taklit edilmi) arnn en az bir kere geleceini tanmlam s c g g s oluyoruz. Yni expects(atLeastOnce()) kullanm sayesinde, taklit edilmi a s nesneye ka kere ar yaplyor olmasn bile test senaryomuza dahil etmemiz c c g mmkn olmaktadr. Bu da nemlidir, unk eer ilem kodlar biz d nesne u u o c u g s s arlmas beklerken hi ar yapmazsa, bu da bir hata durumu olacaktr ve c g cc g bu durumun yakalanmas kodumuzun doruluu asndan faydal olabilir. g g c Taklit nesne uzerinde arlacak metodun ismini #12de tanmlyoruz. #13, c g dn deerini tanmlyor. Bu hazrlklardan sonra, artk AppLogici ararak, o us g c g teste gelen sonucu kontrol edebiliriz. #15te yaplan translate ars, AppLogicden taklit SocketClienta c g yaplan bir takeWordFromJapan arsna sebebiyet verecektir. Biz de zaten bu c g senaryoyu planlamtk ve #11deki expects(atLeastOnce()) tanmnn ses bebi buydu. Beklenen bu arnn cevabn da piirip taklit nesneye hazrlatmtk, c g s s cevap HAI kelimesi olacakt. Bu cevap gelince, sra (esas test ettiimiz) AppLogic classna gelir, transg late kodunun geri kalan iler. HAI grnce evet Trke cevab verilmesi s ou u c gerektiine, if kodlar karar verecektir (eer doru yazlmlarsa). Eer hakikaten g g g s g geriye evet cevab dndrlrse, bu cevab kontrol eden JUnit testimiz, baaryla o u uu s senaryonun getiini rapor edecektir. c g Ustte gsterilen rnek kodlarn tmn JUnitSample projesi altnda bulao o u u u bilirsiniz. Birim testleri iletmek iin ant test komutunu kullannz. s c Kendi Kodumuz ile Taklit Etmek Eer jMock ile taklitleme tekniini kullanmak istemezsek, taklit nesnesini kendimiz g g de yaratabiliriz. Bunun iin yapmamz gereken, taklit edilen nesneden miras c 245

7. Test Etmek alp, taklit edilen metotu tekrar tanmlamaktr (redene). Mesel Socketa Client classnn taklitini elle yle yazabiliriz. so
public class SocketClientManualMock extends SocketClient { private String returnThis; public void setReturnWhichWord(String word) { this.returnThis = word; } // tekrar tanm public String takeWordFromJapan(){ return returnThis; } }

Bu nesnede, grldu gibi, hibir socket ilemi yaplmyor. Japonyadan String o u ug c s almas gereken metot, sadece, daha nceden set edilmi bir String deerini o s g dndrmek uzere ayarlanmtr. Bu dzen, jMock artlarnda grdumz will o u s u s o ug u (returnValue(..)) kullanmna edeerdir. Testin kendisi de yle gzkeceks g so o u tir.
public class TranslateManualMockTest extends TestCase { public void testHai() { SocketClientManualMock mockObj = new SocketClientManualMock(); AppLogic logic = new AppLogic(); logic.setSocketClient(mockObj); mockObj.setReturnWhichWord("HAI"); String answer = logic.translate(); assertEquals("evet", answer); } }

Bu testin de ileyip baaryla geri dndun greceiz. s s o ug u o g Bu yntemin, jMock yntemine nazaran dezavantaj fazladan bir class yazlmasn o o macbur brakmasdr. Bu da kod bazmzda class enasyonuna yol aabilir. c jMock ile d class dinamik olarak uretilmitir, ve hibir ek classa gerek yoks s c tur. Iki yntem arasnda seim yaparken tavsiyemiz, taklitlemeyi nce jMock ile o c o balamak eer bir ekilde taklnr ve ok etrel bir ortamda jMock kullanm s g s c c zorlamaya balarsa, elle taklitleme yaplmaya balanmasdr. s s 246

BIRIM TESTLERI

7.1.3

Hibernate Test Altyaps

SimpleHibernate rnek projesinde Hibernate uzerinden veri tabanna erien o s birok senaryoyu grmeniz mmkndr. SimpleHibernate JUnit test kodlarn c o u u u altrmak iin, komut satrndan ant test komutunu vermeniz yeterlidir. c s c Bu blmde, Hibernate kodlarn test edebilmek iin faydal bir class org/myou c company/util/TestUtil kodlarn greceiz. TestUtil ile, bir test senaryosu o g iin gereken test verisini yklememiz mmkn olacak. c u u u Test Verisi Hibernate (ya da baka tekniklerle) veri eriimi yapan kodlar test etmenin en s s zor taraf test balamadan nce veri tabannda belli bir test verisinin olmas s o zorunluluudur. Bu test verilerin yklenmesini tabii ki yine Hibernatei kulg u lanarak ekleme, gncelleme komutlar uzerinden yapmak mmkndr, fakat, u u u u test etmeye uratmz zaten Hibernate veriye eriim kodlarnn kendisi deil g s g s g midir? Test edilen kodlar teste hazrlk iin kullanmak garip bir tavuk/yumurta c yumurta/tavuk ilikisi ortaya karmaktadr. Bu sebeple test verisi yklemek s c u iin pr SQL kullanarak (SQL komutlar ieren bir dosyadan) veri yklemek c u c u ideal yntem olacaktr. Zaten test iin gereken veri bazen mevcut bir tabano c dan SQL formatnda geliyor olabilir. O zaman bu veriyi bir .sql dosyas uzerinden kullanabilen bir test altyaps bizim iin faydal olacak. c TestUtil kodlar birim testi balar balamaz sfrdan ema kurmak ve veri s s s ykleme ilemleri iin tarafmzdan yazlm bir classtr. Hibernate kodlarn u s c s test etmek iin gereken veri ykleme ilemini TestUtil.createFromFile ve c u s TestUtil.insertFromFile metotlar ile yapabilirsiniz. Yni veri tabannda ema yaratm ve veri yklemesi iin bize iki SQL dosyas a s u c gerekiyor. Bu dosyalardan biri ema uretmemizi salayacak CREATE TABLE kos g mutlar ieren dosya olmaldr, ikincisi, INSERT ieren veri ykleme dosyas c c u olmaldr. Bu iki dosyann bir rneini aada gryoruz. o g s g ou Liste 7.1: tables mysql.sql
DROP TABLE IF EXISTS car; CREATE TABLE car ( license_plate varchar(30) default , description varchar(30) default ) TYPE=MyISAM;

Liste 7.2: sample data.sql


truncate table car; insert into car(license_plate, description) values(34 TTD 2202,ornek description);

Bu dosyalar taban uzerinde iletmek iin TestUtilin iki arsn srasyla s c c g tables_mysql.sql ve sample_data.sql uzerinde kullanyoruz. TestUtil, bu 247

7. Test Etmek dosyalarn ieriini hibernate.cfg.xml iinde belirtilmi tabanda iletecektir. c g c s s Bylece tabana istediimiz rnek veri yklenmi olacaktr. o g o u s Liste 7.3: SimpleCarTest.java
public class SimpleCarTest extends TestCase { public SimpleCarTest() { } public void testCar() throws Exception { Connection c = TestUtil.createTestConnection(); TestUtil.createFromFile("tables_mysql.sql", c); TestUtil.insertFromFile("sample_data.sql", c); try { Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); Car car = (Car) s.get(Car.class, "34 TTD 2202"); assertEquals("ornek description", car.getDescription()); HibernateSession.commitTransaction(); } finally { HibernateSession.closeSession(); } } }

SimpleCarTest ok basit bir testi gerekletirmektedir. Test banda SQL dosyalarnn c c s s belli verileri yklediini bildiimiz iin testin tek yapmas gereken, Hibernate u g g c ile veriye eriimi test etmektir. Ornekte Car elemesi uzerinden Hibernate geti s s test etmi oluyoruz. Hibernate get, kendisine verilen ID uzerinden tek bir ness neyi yklememizi salayan bir ardr. Car elemesindeki licensePlate esi u g c g s og kimlik olduu iin gete (daha nce test verisini yklemi olduumuz) bir lig c o u s g censePlate verince, geriye tek bir nesne gelmesini bekleriz. JUnit birim testi de aynen bunu yapmaktadr. Kontrol amal olarak biraz nce okuduumuz c o g nesne uzerinde description olarak rnek description metnini bulmay amalyoruz (unk rnek veride byledir), ve bu art assertEquals ile konc c u o o s trol ediyoruz. TestUtil kullanan JUnit testleri hakknda bilmemiz gereken dier nemli g o noktalar unlardr: s TestUtilin TestUtil.createFromFile ve TestUtil.insertFromFile metotlarna geilen her sql dosya, CLASSPATH belirtilen bir dizinde mevc cut olmaldr. TestUtil, kendisine iletilmesi iin verilen sql dosyalarn s c CLASSPATH altnda aramak uzere programlanmtr. SimpleHibernate s 248

BIRIM TESTLERI ve dier tm kitap rnek kodlarnda src/sql dizinini biz CLASSPATHe g u o ekledik. Her test banda TestUtil.createFromFile ile emay sfrdan yarats s mamz ok nemlidir, unk kodlama sreci iinde emamz bakas tarafndan c o c u u c s s deitirilmi olabilir. Kodlar ve ema bir btn olduu iin, en son kod, en gs s s uu g c son ema ile altrlmaldr. Bu sebeple her test banda emay sfrdan s c s s s yaratarak, kod ve ema uyumsuzluklarn birim test seviyesinde yakalayas bilmi oluyoruz. Kural #3 balamnda, basit bir alkanlk edinerek (her s g s test banda ema tekrar yaratlr), ema ve kod arasndaki uyumsuzluks s s lar erkenden yakalama ansna kavuuyoruz. Emin olun ki bu uyumsus s zluklarn kod ierisinde haftalarca kalp bymesi kod kalitesi asndan c u u c hi iyi olmayacaktr! c Birim test felsefesine gre her birim testi kendi kendine yeter bir ekilde o s yazlmaldr, ve bir birim testinin sonucu dier birim testini etkilememeg lidir (her birim testi banda emay sfrdan kurmak iin bir sebep daha, s s c unk bir test sonucunu bir tekini veri taban uzerinden bile etkilememec u o lidir). Hibernate Birim Testleri Hangi Tabana Balanyor? g Ornek projelerimizdeki birim testleri, testlerin iledii makinadan eriilebilen s g s bir veri tabannn varln art komaktadr. Fakat gereksinimler bundan ibaretg s s tir. Mesel testlerimizin almas iin tabanda hibir emann kurulmu olmas a c s c c s s gerekmez. TestUtil aracl ile emay sfrdan kurmak JUnit birim testleri g s iinden otomatik olarak gerekletirilecektir. c c s Not: TestUtil bu balamda uzun bir deiim srecinden geti. g gs u c Kodun daha nceki versiyonlar, birim testleri ileten kiinin bilo s s gisayarnda bir veri tabannn olamayacan ihtimale katarak, SQL g ema scriptlerini MySQL ya da Oracle formatndan HSQLDB fors matna annda evirmeye urayordu. HSQLDB, gml (embedc g s o uu ded) bir taban olduu iin, kullanmak iin bir servis balatmaya g c c s gerek brakmaz, bu sayede JUnit tarafndan rahatlkla hafzada balatlarak, yklenip testler iin hazr hle getirilebilir. Bu yntemi s u c a o takip etmekte ama, test iletici uzerinde en az klfeti getirmek idi. c s u Fakat, bu yntemin ilemesinde problemler bulunmutur; o s s 1. HSQLDB, baz etrel Hibernate sorgularn iletmekte probc s lemler karm c s 2. Oracle ya da MySQL ema scriptlerinden HSQLDB scriptlerine s otomatik olarak evirim yapan Perl scriptlerinin bakm ve c kodlamas fazla zaman alc bir eylem hline gelmitir. a s 249

7. Test Etmek Bu sebeple, Kural #3 nda birim testlerini iletmek isteyen her sg s programcnn ciddi bir veri taban urnne eriiminin olmas pren u u s sibini takip etmek uygun gzkmtr. o u us u Deiik Test Senaryolar gs Eer birim testlerinizde deiik senaryolar test etmek isterseniz, bu, ou zag gs c g man deiik rnek veri kullanmak anlamna gelecektir. Bu yeni senaryolarda gs o (ve JUnit testlerinde), emay ureten satr nceki rneklerimizdeki gibi kalacak, s o o fakat deiik bir rnek veri dosyasn ileten ve deiik deerleri assertEquals gs o s gs g ile kontrol eden bir kod olacaktr. Mesel, bu ekilde bir yeni testi altta grelim: a s o Liste 7.4: SimpleCarTestManyRows.java
public class SimpleCarTestManyRows extends TestCase { public SimpleCarTest() { } ... public void testCarNew() throws Exception { Connection c = TestUtil.createTestConnection(); TestUtil.createFromFile("tables_mysql.sql", c); TestUtil.insertFromFile("sample_data_2.sql", c); try { Session s = HibernateSession.openSession(); HibernateSession.beginTransaction(); Car car = (Car) s.get(Car.class, "52 TT 30"); assertEquals("description 4", car.getDescription()); HibernateSession.commitTransaction(); } finally { HibernateSession.closeSession(); } } }

Yeni testimizin deiik veriye ihtiyac var. Bu veriyi, alttaki dosyadan salayabiliriz. gs g Liste 7.5: sample data 2.sql
truncate table car; insert into car(license_plate, description) values(34 TTD 2202,description 1); insert into car(license_plate, description) values(14 TF 399,description 2);

250

KABUL TESTLERI
insert into car(license_plate, description) values(34 RF 493,description 3); insert into car(license_plate, description) values(52 TT 30,description 4);

Grldgu gibi yeni testte yklenen veri sample_data.sql deil, sample o u u u g _data_2.sql adl dosyadr, unk testimiz iin yaratmamz gereken senaryo c u c bunu gerektiriyordu. Yeni veri uzerinden testin kontrol edecei araba nesnesi, g 52 TT 30 nolu plakay tayan arabadr. Test, get komutu ile bu nesneyi ykler s u assertEquals ile sonucu kontrol eder.

7.2

Kabul Testleri

Birim testleri en ufak modl (metot) baznda test yapyorsa, kabul testleri u de (acceptance test) programn dndan, birden fazla modle dokunabilecek s u ekilde bir kullanc gznden test etmemize yarar. Kabul testlerine sektrde s o u o fonksiyonel (functional) test, ya da entegrasyon (integration) testleri isimleri de verilmektedir. Kabul testleri mmkn olduu kadar d sistemlerle entegrasyu u g s onu yaplm bir sistem uzerinde gerekletirilmelidir. s c s Kabul testlerini en basit ekilde elle (uygulamay bizzat kullanarak) yaps mak mmkndr. Uygulamamz test edilmeye hazr hle gelince kodlar test u u u a makinasna gnderilir, ve bir test kullanc(lar) belli test senaryolarn uyguo lama uzerinde iletip, uygulama iin kabul testlerinden geti ya da kald ra s c c poru verebilirler. Test kullancs kabul testlerini gerekletirirken elinde belli c s test senaryolar olur. Kullanc bu senaryolar srasyla program uzerinde iletir s sonularn kontrol eder, ve bir yere not eder. Hatal gzken sonular, hata c o u c takip sistemine (bug tracking system) girilir, ve dzeltme sreci balam olur. u u s s

7.2.1

Otomatik Kabul Testleri

Elle yaplan testler iin zaman ve insan gc harcanmas gerekir. Fakat yaplan c u u iin olduka mekanik olmas sebebiyle otomatik yaplan kabul testleri de artk s c tercih edilmeye balanmtr (Kural #7). Kurumsal Web ortamnda otomatik s s kabul testleri iletmek iin birok urn mevcuttur; Bizim tavsiyemiz, 5.3.1 s c c u blmnde ilediimiz ve yk testleri iin kullanlan JMeter urnn kabul ou u s g u c u u u testleri iin kullanmaktr. c JMeteri bu ekilde iki amal kullanabilmemizin sebebi, bu urnnn Web s c u u u uygulamasndan gelen cevaplar ileyebilen bir birim salamasdr; Kullanacamz s g g bu birim, Reponse Assertion adl birimdir. JMeter Kullanm Bir kabul testinin yk testinden en nemli fark, kabul testi iin balanan u o c g tek Threadin (sanal kullanc olarak) yeterli olmasdr, unk test edilen arka c u 251

7. Test Etmek plan kodlarnn leklenebilmesi deil, doru alp almaddr. Sekil 7.1 oc g g c s c s g uzerinde gereken Thread ayarlarn gryoruz. ou

Sekil 7.1: Kabul Test iin JMeter Thread Says c Geri kalan ayarlar, 5.3.1 blmnden tandk olacaktr. JMeter sanal kulou u lancsnn bir dinamik sayfaya balanp forma test deerleri girmesi iin Http g g c Request biriminin eklenmesi ve gerekli parametrelerin bu birime verilmesi yeterlidir. Ornek iin StrutsHibPerformance projesinin resources/accepc tance-test-add.jmx dosyasnda iinde tanmlanm /kitapdemo/add-car. c s do birimine bakabiliriz. Bu rnek kabul testini StrutsHibPerformance projesi o uzerinde kullanabiliriz. Ornek test dosyasn, JMeter mens File | Open ile aabilirsiniz. Sekil uu c 7.2 uzerinde kabul testin tm birimlerini, Sekil 7.3 uzerinde ise /kitapdemo/ u add-car.do biriminin detaylarn gryoruz. ou Bir kabul testinin yapmas gereken doruluk kontrollerini JMetern Reg sponse Assertion birimini kullanarak yapabiliriz. Bu kontrol, JUnit birim testlerinden kullandmz assert metotlar ile edeer bir zelliktir; Amacmz, g s g o testin bekledii cevap deerleri uygulamadan geri gelmezse, bu kontrol edici g g birim ile bu hatay yakalayp bize bildirmesini salamaktr. g Response Assertion birimi, yaplan bir Web isteinden sonra geri gelen g cevap (response) iindeki deerlere bakabilme yeteneine sahiptir. Bu cevap c g g ierii, bir Web sayfasn taraycnz ile ziyaret edince taraycnza gnderilen c g o ierik ile ayndr. Taraycya gelen HTML ierii grmek iin Mozillada View c c g o c | Page Source seeneini kullanlabiliriz. c g Response Assertion birimininin kontroln yapabilmesi iin, hangi Web u u c isteinin ieriine bakacan bilmesi gerekiyor. Yni Response Assertion her g c g g a zaman bir Http Requeste alt birim olarak eklenmelidir. O zaman Response Assertion eklemek iin, bir Http Requeste tklayp, mouse sa tklama ile c g Add | Assertions | Response Assertion seeneini semeliyiz. Eer konc g c g trol birimini yanl yere eklediysek, bu birimi srkle/brak ile gereken Http s uu 252

KABUL TESTLERI

Sekil 7.2: Ornek bir Kabul Testi

Sekil 7.3: Araba Eklemek

253

7. Test Etmek Request uzerine gtrp, Add As Child seeneini kullanmalyz. Alt birim ouu c g olarak eklenmi Response Assertion birimini Sekil 7.2 uzerinde gryoruz. s ou Orneimizde kullanlan Response Assertion ieriini Sekil 7.4 uzerinde grlmekg c g ou tedir.

Sekil 7.4: Araba Kontrol Yapan Response Assertion u Bu cevap kontrolnde, cevap metni iinde aranacak deerler 34 TT 2000 u c g ve benim arabam kelimeleridir. Bu kelimelerin orada olmas lzmdr, unk add a c u -car.do Struts Actionn iini bitirdikten sonra ynlendirmeyi main.doya yas o par. main.do ise, o anda sistemde olan tm arabalar listelemek ile ykmldr, u u u u u ve biz de daha nceden add-car.do ile plakas 34 TT 2000 ve aklamas o c benim arabam olan bir arabay sisteme eklettirdiimiz iin, bu kelimelerin g c araba listesinde olmasn beklememiz normldir. Run | Start ile iletebileceiniz a s g ekleme kabul testinin sonular Aggregate Report biriminde yle (7.5) gzkec so o u cektir. Eer Error kolonu altnda 0.00% gryorsak, tm testlerin baar ile g ou u s getiini anlarz. c g

Sekil 7.5: Sonular c Ozet olarak, JMeter ile bir Web uygulamasn test etmek iin, unlar yapc s mak gerekir: 254

KABUL TESTLERI Test edilen Actiona Http Request ile baz test deerleri gndermek g o struts-config.xml dosyasna bakarak, i bittikten sonra ynlendirmenin s o nasl yaplacana bakmak g Bu ynlendirmeye gre, hangi deerlerin geleceine gre bir kontrol edici o o g g o Response Assertion birimini Http Request altna eklemek Eer Http Request birimlerini elle eklemek istemiyorsak, 5.3.1 blmnde ang ou u latld gibi, kullanc program taraycda kullanrken, hareketlerinin kaydedilmesini g salayabiliriz. g Kontrol Ceitleri s Bir Response Assertion tanmlarken, yapacamz ayarlardan bir tanesi, hangi g ierik kontrolnn yapldn tanmlamaktr. Ustte gsterilen kontrol, bir c u u g o mevcudiyet kontrol, ya da, bizim beklediimiz deerin olmasn bekleyen u g g trden bir kontroldr. Fakat bir metnin olma kontroln yaptmz gibi, olu u u u g mamama kontroln de yapabiliriz. Bu durum, mesel bir arabann sistemden u u a silindii delete-car.do Action iin gereklidir. Bu Action bir araba sildii g c g iin, mantken o arabann bir sonraki araba listesi ekrannda olmamas gerekec cektir. Eer Response Assertionn yapt kontrol eidini deitirmek istersek, g g c s gs bunu Pattern Matching Rules ayarlar altndan yapabiliriz. Mesel, rnek a o olarak biraz nce eklediimiz arabay delete-car.do ile silelim, ve delete- o g car.do altna koyacamz bir kontrol Sekil 7.6 uzerindeki gibi olsun. Bu kong troln detaylarnda, uymama kontrol iin Contains seeneine ek olarak, Not u u c c g (deil) seeneini de sememiz gerekti. Eer Not seilmemi olsayd kontrol, g c g c g c s pozitif bir kontrol olacakt.

Sekil 7.6: Uymama Kontrol u 255

7. Test Etmek Bu testi de iletince, geriye gelen sonu Sekil 7.8 uzerindeki gibi olacaktr. s c Yine hata yzdesi 0.00% seviyesindedir, yni tm testler baaryla gemitir. u a u s c s

Sekil 7.7: Ekleme ve Silme Testleri

Sekil 7.8: Ekleme ve Silme Test Sonular c

7.3

Ne Kadar Test Gerekli?

Birim ve kabul testlerini ciddi bir ekilde uygulamaya karar verilince ve teknikleri s renilince, programclar en ok dundren kararlardan biri ne kadar testin og c us u yeterli olduu sorusudur. Ne de olsa testler, varl ve yokluu gereklilik kodg g g lar seviyesinde kontrol edilen iler deillerdir. Eer yazmazsak, yazlmayan s g g testler yaplmayan kontrollerdir. Uygulamamz uzerinde bir deiiklik olmaz. gs 256

Ne Kadar Test Gerekli?

7.3.1

Birim Test Miktar

Birim testleri iin ne kadar sorusunun cevabnda iyi bir kulaa kpe kural c g u (rule of thumb) ncelikle kodun ne kadar etrel olduu ile alkaldr. Kodun o c g a etrelliini en basit olarak, ustn kr bir ekilde, koda plak gzel bak c g u ou s c o s kullanarak bile yaplabilir. Ne zaman ki bir metot kodlarnn girinti (indentation) seviyesi iki ya da daha fazla seviye ieri giriyor, o zaman o metotu test c etmemiz iyi olacaktr. Girinti seviyesi, bir metot iinde while, if, else komutc larnn kullanmna bir iaret olduu iin, basit bir litmus testi olarak faydal s g c bir gstergedir. o Dier artlarda, birim testi yazmak ve yazmamak karar iin her durumu g s c ayr ayr tartabiliriz. Biz, mesel Hibernate kullanlan kurumsal kodlarmzda a her kalc nesne ve o nesne uzerindeki her ilikiyi bir ekilde kullanan (genelde s s bir get komutu ile) bir testi yeterli buluyoruz. Bu eit bir test en azndan c s elemelerin doru yapldna dair bize bir rahatlk verecei iin yaplmas fays g g g c dal olmaktadr. Ama her kalc nesne iin drt ilemin (ekle, sil, gncelle, c o s u ykle) test edilmesi fuzuli (overkill) olabilir. Bu tr birim testlerini yazmak u u hzl gelitirmenize engel olaca iin tarafmzdan tavsiye edilmeyecektir. s g c

7.3.2

Kabul Test Miktar

Felsefe olarak unu da eklemek gerekiyor. Kabul testleri birim testlerinden s daha nemlidir. Tecrbe gsteriyor ki, ufak, mikro seviyede yazlan testlerden o u o geen ve doru alt zannedilen bir uygulamann btnnn almamas c g c s g uu u u c s mmkndr. Ozellikle birden fazla d sistemin biraraya geldii kurumsal uyguu u u s g lama dnyasnda i ve d entegrasyon, sistemin ileyii iin had safhada nem u c s s s c o tar. O zaman kabul testlerini, zellikle anlattmz ekilde otomatik olanlarn s o g s hazrlamamz, ve gncel tutmamz nemlidir. u o Kabul test miktar asndan, en azndan, her orta ve ust zorlukta olan c u gereklilik (functionality) ve bu gerekliliin deiik senaryolarnn test edilmesi g gs iyi olacaktr. Eer daha fazla zaman ve kaynak ayrabiliyorsanz, en basit sayg falar bile otomatik test havuzunuza dahil etmemiz, projemiz iin ileri safhalarda c ok faydal bir seim olacaktr. c c

257

7. Test Etmek

258

Bl m 8 ou

Nesnesel Tasarm

Bu Bl mdekiler ou Nesne odakl tasarm ve programclk Tasarm dzenleri u Mimariler

259

8. Nesnesel Tasarm esne odakl tasarm ve programclk gnmzde o kadar geni kabul u u u s grm haldedir ki, bu kavramlar sahneye kmadan nce nasl program o us c o yazdmz (ya uygun olanlar) bile bazen hatrlayamaz oluyoruz. Fakat g s aslnda kurumsal programcln en popler dili Javay, onun temel ald C++, g u g ve Smalltalk dillerini 1967 ylnda km tek bir dile balamak mmkndr: c s g u u u Simula. Simula yaratclar (Kristen Nygaard, Ole-Johan Dahl) dnyann ilk nesneu sel dilini simulasyon programlar yazmak amac ile yarattlar. Ayrsal olay simulasyonu (discrete event simulation), bir matematiksel sistemi cebirsel yntemo lerle (analitik modelleme -analytical modeling-) ile deil, sistemdeki aktrleri g o bir nesne olarak betimleyip, onlarn uzerine gelen olaylar (event) gerek dnya c u artlarnda olaca gibi ama sanal bir ortamda tekrar yaratarak bir sistemi s g zmeye verilen addr. Baz problemlerin zlebilir (tractable) bir analitik co co u modeli kurulumadndan, ayrksal olay simulasyonu popler bir zm olarak g u co u kullanm bulmutur. s Nesne odakl tasarm ve programlama kavramlarnn ilk kez simulasyon amal yaratlm bir dil iinde ortaya kmalar kesinlikle bir kaza deildir [3, c s c c g sf. 1122]. Nesne kavram, gerek dnyadaki bir nesneyi ok rahat yanstt iin, c u c g c bu ynde kullanm bulmas rahatt. Daha sonra Simula kullanclarnn da fark o ettii uzere, simulasyon dnda Simula dilinin genel programclk iin yararl g s c olabilecei anlalmaya balanmtr. Bundan sonra nesne odakl programlama g s s s kavramlar genel programc kitlesine de yaylmaya balad. s Simulann zellikleri dier diller tarafndan hzla adapte edilmeye baland: o g s Xerox PARC irketinde Alan Kay, Simuladan esinlendii nesnesel odakl kavrams g lar, grak ortamda programlama ortam salayan yeni projesine dahil ederek g Smalltalk dilini yaratt (1972). Eer Simula akademik evreleri etkilediyse, g c Smalltalk Byte dergisinin unl 1981 Austos saysnda kitleleri etkilemitir: Bu u g s sayda grsel bir Smalltalk programlama ortam ilk kez genel programc seyiro cisine nesneleri grsel bir ekilde tantyordu. Hakikaten de Smalltalk nesnesel o s diller iinde grsel gelitirme ortamn ilk destekleyen dil olarak gnmzdeki c o s u u u modern IDElerin ounun kir babas saylmaktadr. c g Smalltalkn getirdii ilgin bir zellik class (nesne tanm) ile nesne kavram g c o arasndaki fark ortadan kaldrmasyd; Smalltalk dnyasnda herey bir nesu s neydi. Bu durum, gnmzde kullanlan nesne odakl programlama teriminin u u u bile Smalltalktan ne kadar etkilendiini gstermektedir unk bu birleim, ne g o c u s yazk ki, her dier nesne odakl dil iin doru deildir: Java, Eiel, C++ g c g g gibi gcl tipleme takip eden dillerde class ve nesne ok net bir ekilde biru u c s birinden ayrlr, yni nesne odakl programlama terimi, gcl tipleme kula u u lanan bir dil iin class odakl programlama olarak deitirilmelidir (neyse!). c gs Fakat Smalltalk dier noktalarda, mesel her eyi nesne hline getirmi olmas g a s a s sayesinde debugger, nesne gezici (object browser) gibi koda erimesi gereken ek s aralarn iini rahatlatabilmeyi baarmtr. c s s s Smalltalkun dezavantaj, zayf tipleme kullanan dinamik bir dil olmasdr ve bu sebeple Smalltalk kullanan programlar ciddi performans problemleri 260

NESNESEL TASARIM VE TEKNOLOJI yaamtr. Sebebini yle aklayabiliriz: Statik tipleme kullanan Java, Eiel s s so c ve C++ derleyicilerinin baz performans iyiletirmelerini programclarna ders leme annda sunmalar mmkndr: Mesel, bu dillerin derleyicileri miras (inu u u a heritance) durumunda fonksiyonlar bir dizin olarak nceden tutarak, dinamik o balamay (dynamic binding) anlk/sabit zamanda zebilirler. Smalltalk, dig co namik bir dil olmas sebebiyle bu tr iyiletirmelerden faydalanamamtr [3, u s s sf. 1134]. Bu hatalar, AT&T Bell Labarotuvarlarnda alan Bjarne Stroustrup tarafndan c s dikkate alnarak, tekrarlanmamtr. Simulann ana kavramlarn C diline tayarak s s C++ dilini oluturan Stroustrup, zellikle Cden nesnesel kavramna gei yaps o cs mak isteyen programclara 80 sonlar ve 90 balarnda ok ideal bir seenek suns c c may baard. Bu zamanlarda C++, Kurumsal Yazlm Mdrleri (IT Manager) s u u iin her iki dnyann en iyi birleimiydi: Mevcut programclar korkutmayacak c u s kadar C, ama ileri kavramlar renmek isteyenlerin sevecei kadar nesnesel. og g Fakat C++n nesnesel dil eklerinin gereinden fazla etrel olmas ve C++n g c bir p toplaycy desteklememesi gibi sebepler yznden, 90l yllarn ortaco u u larnda sektr kurumsal uygulamalarda Java diline doru kaymtr. o g s Java, C++n szdizimini daha temizletirerek p toplayc eklemi, ayrca o s co s ezamanl (concurrent) ve network uzerinde programlamaya paketten kt s c g hliyle destek vermesi ile, nokta com patlamas (dot com boom) ile ayn anda a anlr ve bilinir bir duruma gelmitir. Bu yzden daha iyi bir C++ arayan s u kurumsal programclar, ve yeni Internet ortamnn gerektirdii programlama g iin Java, gerekeni tam karlayan bir dil hline geliyordu. Gnmzde Java c s a u u u kurumsal programcln en yaygn kullanlan dili hline gelmitir. g a s

8.1

Nesnesel Tasarm ve Teknoloji

Kurumsal programclkta kullanlan dilin temizliine ek olarak, kullanlan yan g teknolojiler ve onlarn gerektirdii arayzler (API) nesnesel tasarmmz uzerinde g u kesinlikle ok etkilidirler. Nesnesel tasarmn ve yntemlerinin ilk yaygnlamaya c o s balad 80li ve 90l yllarda yaplan nemli bir hata, d teknolojilerin yok s g o s saylmas ve nesnesel tasarmn bir bolukta (vacuum) ierisindeymi gibi yaplmasnn s c s cesaretlendirilmeydi. Bu tavsiyenin projeler uzerinde etkisi ldrc olmutur, o uu u s unk bir projede kullandnz her teknoloji, nesne yaplarnz etkiler. c u g Dier programclk dallarnda bu her zaman geerli olmayabilir. Mesel bilg c a imsel forml hesab (number crunching) yapmas gereken trden programlar, u u d sistemlerle fazla etkileime girmezler. Girdi olarak bir dosya alrlar, ve kt s s c olarak bir dier dosya uretirler (ya da izim (plot) basabilirler). Kyasla bir g c kurumsal sistem, en azndan bir veri taban urnyle, ek olarak ta uygulama u u servisi, JMS ile asenkron iletiim, e-mail, yardmc ktphaneler gibi birok d s uu c s ara ile iletiim hlinde olacaktr. Forml hesab yapan programlarda d sisc s a u s temleri yok sayarak daha rahat nesnesel tasarm yapabilirsiniz, ama kurumsal 261

8. Nesnesel Tasarm sistemlerde nesnesel tasarm nerede kullanacamz ok iyi bilmemiz gerekeg c cektir. Nesnesel tasarm yapacamz yer, programnzn ileyi kontrolnn altyap g s s u u kodlarndan sizin yazacanz kodlara geldii yerde balar, ve tekrar d teknolog g s s jiye getiinde biter. Burada vurgulamak istediimiz bir ncelik mentalitesi c g g o farkdr: Yaplmas yanl olan, teknolojiden habersiz bir ekilde irin ve gzel s s s u nesneler tasarlayp onu sonra teknolojiye balamaktr. Bunun yerine yaplmas g gereken, nce teknolojiyle nasl konumamz gerektiini anlamamz ve sonra o s g iletiim noktalarn iyice kavradktan sonra, arada kalan bo blgeleri nesnesel s s o tasarm ile doldurmamzdr. Bunu bir rnek ile anlatmaya alalm: o c s Sisteme mteri eklemesi gereken bir uygulama dunelim. Bu mteri veri us us us g yaps hakknda tutmamz gereken zellikler (attributes) biliniyor olsun. Oeler o alndktan sonra uygulamann baz doruluk kontrolleri yapmas gerekiyor, g bunlar isim ve soyadnn mecburi olmas ve e-mail iinde @ iaretinin bulunc s masnn kontrol edilmesi gibi ilemler olacaktr. Daha sonra, baka bir ilem ile s s s mteri veri tabanna yazlacaktr. us Bu gereklilik listesi uzerinden, baz nesnesel programclar tasarma direk balanabileceini savunurlar. Ideal bir modeli de yle kurabilirler (Sekil 8.1). s g so

Customer
+name +lastName +email +setName() +getName() +getLastName() +setLastName() +setEmail() +getEmail() +validate() +save()

Actor

Sekil 8.1: Yanl Mteri Nesnesi s us Bu modele gre nyz, bir Customer (mteri) nesnesini yaratacak, uzerinde o o u us setName, setLastName, vs. ile gereken verileri koyacak, daha sonra veri doruluk g kontrol iin validate arsn yapacak, ve en sonunda save ile mteri nesu c c g us nesini kaydedecektir. Fakat, bu teorik model hibir teknolojiyi dikkate almamtr, bu sebeple c s tasarm etkileyebilecek baz ek faktrler atlanmtr. Bakalm teknolojiyi eko s leyince modelimiz etkilenecek mi? Mesel eer nyzde Struts altyapsn kula g o u 262

NESNESEL TASARIM VE TEKNOLOJI lanyorsak, balanan (client) tarafnda doruluk kontrol yapmann bir Struts g g u teknii vardr. Ozellikle rnekte gsterilen mteri nesnesinde yaptmz trden g o o us g u kontroller (isim, soyad, e-mail) iin, Javascript bazl alan bir altyap mevc c s cuttur. Bu doruluk kontrol altyaps, Strutsn ayar dosyasndan struts- g config.xml ayarlanr, ve modelde grlen trden bir Java kodu yazlmasn ou u gerektirmez. Bu yzden, modelimize koyduumuz validate metodu tamamen u g gereksizdir. Ayn ekilde, eer projemizde Hibernate kullanyorsak, kalclk metodu s g olan save, mteri nesnesi uzerinde deil, org.hibernate.Session nesnesi us g uzerindedir. Hibernate savee parametre olarak mteri nesnesini gemek gerekir, us c save metodu mteri uzerinde arlmaz. Yine teknolojiyi dikkate alnmadan us c g modelin eksik olacan kantlam oluyoruz. g s Fakat bitmedi. Simdi nyz ile Customer nesnesi arasnda olabilecek arlar o u c g ele alalm. Mesel, nyz teknolojisi Swing olsun, ve bu sebeple birok Swing a o u c nyznn a (network) uzerinden mteriye erimesi gereksin. Pr nesnesel o u u u g us s u modelleme yaptmz iin ve teknolojiyi dikkate (!) almadmz iin de, 8.2 g c g c uzerindeki yapy kuruyoruz.

Customer
+name +lastName +email adds +load() +addUser() +validate() Actor +setName() +getName() +getLastName() +setLastName() +setEmail() +getEmail() +save()

Page

Sekil 8.2: Network Uzerinden Mteri Eklemek us Bu model optimal alr m? Eer bir uygulamann performans en az c s g doruluu kadar nemliyse, bu modelin hzl alsmas nemli olmaldr. Ne g g o c o yazk ki bu soruya cevap, hayr olacaktr. Dikkat edersek nyz, yni Page o u a (sayfa) nesnesi, new ile bir Customer nesnesi yarattktan sonra, bu nesne uzerinde s set metotlarn aracaktr. Ite problem burada ortaya kacaktr, unk netc g c c u work uzerinde eriim kurallarna gre, ufak ufak set arlar yapmak yer s o c g ine, tm gereken parametreleri birarada paketleyerek tek bir defada hepsini u gndermek daha hzldr. Kurumsal programclkta ufak ufak ve ok ar yao c c g pan sistemlere geveze (chattery) sistemler denmektedir, ve bu tr mimarilerden u kanlr. c O zaman, modelimize arayz daha geni olan yeni bir class daha eklememiz u u s 263

8. Nesnesel Tasarm gerekiyor. Bu class, d dnyaya gsterilen arayz olacaktr, unk parames u o u c u tre listesini network uzerinden gndermeye daha elverili durumdadr. Bu yeni o s model, Sekil 8.3 uzerinde grlebilir. ou

Page
+load() +addUser() +validate() network

CustomerService
+addCustomer(name,lastName,email)

Actor

Customer
+name +lastName +email +setName() +getName() +getLastName() +setLastName() +setEmail() +getEmail()

Sekil 8.3: Doru Mteri Modeli g us Bu ekil uzerinde yeni bir class, CustomerService gryoruz. Bu class hangi s ou datk nesne teknolojisini kullanyorsak, o ekilde uzaktan eriime alacak olan g s s c classtr. Ozet olarak, ilk yola ktmz modelden olduka uzaklatk. Metot valic g c s date, hem Struts hem de Swing ortamnda balanan tarafa alnmas gereken g bir metottu, bu yzden Customerdan kartld. Metot save, kalclk arac u c uzerinde olacakt, bu sebeple kartld. Ve son olarak uzaktan eriim iin ilk c s c modelde hesaba alnmayan CustomerService class eklendi, bylece Customer o nesnesinin uzaktan arlmasn engelledik. c g

8.2

Modelleme

Teknolojinin kontrol bize brakt ve bizim kontrol geri verdiimiz noktann u g u g arasnda (ve hla teknolojiyi aklmzda tutarak) artk klasik anlamda moda elleme yapabiliriz. Tabii en teorik, ve teknolojiden bamsz olduunu iddia g g eden modeller bile tek bir teknolojik nkabul yapmaktadrlar; Bir nesnenin o 264

Modelleme dier bir nesneye yapt metot arsnn milisaniye seviyesinde ve ayn JVM g g c g iinde iletilecei nkabulu. Blmmzn geri kalannda bu teknolojik nkabc s g o ou u u u o ule dayanarak istediimiz byklkte ve sayda class modelimize koymakta, g u u u ve herhangi bir metotu bir classtan tekine aktarmakta saknca grmeyeceiz. o o g

8.2.1

Prensipler

Modellerimiz iin takip etmemiz gereken basit prensipler unlar olacaktr: c s Fonksiyonlarn yan etkisi olmamaldr. Kurumsal uygulamalarda, model iin class seerken ilikisel modelde (veri c c s taban emasnda) tablo olarak planlanm birimlerin class hline gelmesinde s s a bir saknca yoktur. Bu iliki her zaman birebir olmayabilir, ama emamzdaki s s tablolarn byk bir ounluunu modelimizde class olarak grlecektir. u u c g g ou Bir classn metotlar ve fonksiyonlarn bir alveri listesinin kalemleri s s gibi grmeliyiz. Bir class d dnyaya birden fazla servis sunabilir, ve o s u htta sunmaldr. Bir class sadece tek bir i iin yazlmamaldr. a s c Uygun olduu yerde, tasarm dzenleri (design patterns) faydal aralardr. g u c Erich Gamma ve arkadalarnn paylat dzenler iinden s s g u c Command Template Method Facade Singleton kurumsal sistemlerde kullanlan dzenlerdir (bunlarn haricindeki Gamma u dzenleri kullanm grmez). u o Hibernate ile elediimiz POJOlara set ve get haricinde metotlar ekles g mekte saknca yoktur. Simdi bu prensipleri teker teker aklayalm: c

8.2.2

Fonksiyonlarn Yan Etkisi

Bir fonksiyon, geriye bir sonu dndren bir ardr. Bu geri dndrlen c o u c g o uu deer, ya o ar iinde anlk yaplan bir hesabn sonucu, ya da nesnede tug c g c tulmakta olan bir nesneye ait referans deeri olacaktr. Her ne olursa olsun, bir g fonksiyon bir deer dndrmekle ykmldr. Kyasla metotlar geriye hibir g o u u u u u c deer dndrmezler. Bu yzden metot dn tipi olarak void kullanmak gerekir. g o u u o us Bir fonksiyonun grevi, raporlamaktr. Metotlar nesne iinde bir eyler o c s deitirmek iin kullanlr. Eer bir rnek vermek gerekirse bir nesneyi, bir gs c g o radyo gibi dunebiliriz. Bu radyoda metotlar, kanal deitirme, ses ama/kapama us gs c 265

8. Nesnesel Tasarm gibi dmelerdir. Fonksiyon ise, radyonun hangi kanalda olduunu gsteren bir ug g o ibre olabilir. Bu yzden, fonksiyonlarmz yazarken nesne iinde deiiklik yapmamalar u c gs iin ok zen gstermeliyiz. Bu prensibe dikkat etmeyen ve arlnca nesnede c c o o c g deiiklie sebep olan fonksiyonlara yan etkisi olan fonksiyonlar denmektedir, gs g unk fonksiyonun ana amac dnda bir yan etkiye sebebiyet vermitir; Nesc u s s nenin i verisinde deiiklie sebep olunmutur. Radyo rneimize dnersek, c gs g s o g o dunn ki hangi kanalda olduumuza baknca radyonun kanal deiiyor! Byle us u g gs o bir radyo muhakkak pek kullanl olmazd, unk bir nesne hakknda bilgi als c u mak istediimizde, o bilgi alma ileminin, nesne uzerinde bir deiiklik yapg s gs mamasn bekleriz. Nesnesel odakl tasarmmzda bir fonksiyon yazarken, ayn mantk ile dunmeliyiz. Fonksiyonlarmz deiiklie sebep olmuyorsa, iimiz us gs g c rahat bir ekilde bu fonksiyonlar istediimiz kadar arabiliriz. s g c g

8.2.3

Veri Taban ve Nesnesel Model

Model iin class semek, ou nesne odakl tasarm literatrnde ilenen bir c c c g uu s konudur, ve birok kulaa kpe (rule of thumb) kural ortaya atlmtr. Mesela c g u s dilbilgilsel bir yntem syledir: Gereklilikler (requirements) dokmannn cmlelerindeki o o u u isimler (noun) seilir ve bunlardan bazlar class olarak seilir. Bu ynteme gre, c c o o bir gereklilik dkmanndaki u cmlede; o u s u Asansr hareket etmeden nce kaplarn kapatmaldr, ve asansr o o o bir kattan teki kata her hareket ediinde veri tabannda bir kayt o s yazlmaldr asansr, kat ve kap birer class aday olarak seilmelidirler. o c Fakat byle basiti bir yntem ne yazk ki bizi fazla uzaa gtrmez. Insan o c o g ou dili deiik nanslara ok aktr ve ok daha kat kurallara gre yazlmas gs u c c c o gereken bir bilgisayar sistemi iin bizi yanl yne sevkedebilir. Mesela ustteki c s o rnekte aslnda class olmas gereken ey, harekettir. Ama bu kelime isim deil o s g bir il olduu iin, yntemimiz tarafndan seilmemitir [3, sf. 723]. g c o c s Kurumsal uygulamalarda dilbilgisel yntem yerine veri tabanndaki tabloo lara bakarsak, kullanmamz gereken classlar hakknda daha iyi bir kir edinebiliriz. Mesel ustteki rnekteki hareket, ilikisel modelleme srasnda kesinlikle a o s

Sekil 8.4: Java ArrayList Bir Makina Olsayd 266

Modelleme yakalanacak bir tablo olduundan, bu tabloya bakarak modelimize ayn isimde g bir class ekleyebiliriz. Tabii emamzdaki her tabloyu bir class hline getirmemiz gerekmez. Mesel s a a daha nce kullandmz Garage ve Car rneine gelirsek, bu iki tablo arasnda o g o g oka ok eleme yaptmz durumda bir ara tablo (cross reference table) kullanc c s g mamz gerekecektir. Bu tablonun nesne modeline yanstlmas gerekmez. Sekil 8.5 uzerinde bu elemeyi gryoruz. s ou

Sekil 8.5: Semadaki Her Tablonun Nesne Modeline Yanstlmas Gerekmez Bu elemede GARAGE_CAR adl tablo, nesne dnyasna yanstlmamtr (bu s u s elemenin Hibernate uzerinden nasl yapldn anlamak iin 2.5.3 blmne s g c ou u bakabilirsiniz.

8.2.4

Metotlar ve Alveri Listesi s s

Class seerken ezamanl olarak aklmzn bir kesinde bir seim daha yaparz; c s os c Hangi metotlar ve hangi fonksiyonlarn bir class uzerinde olaca seimi. Zih g c nimizde belli servisler ile veriler biraraya geldiinde, bu birliktelikten bir class g doar. Peki bu birliktelii bulmak iin bir yntem var mdr? Bu i iin nasl g g c o s c bir zihin durumu (mindframe) iinde bulunmalyz? c Tek Amal Class c Nesnesel tasarmda tek bir servis salayan classlardan kanmamz gerekir, g c unk bu tr classlar, hla class modln bir servisler listesi olarak grmediimizi c u u a uu u o g gsterir. Bu tr nesneleri, onlar belgeleyen dokmanlardan rahata anlayao u u c bilirsiniz, genellikle yle trif edilirler: Bu nesne xxx iini yapyor. Bir xyz so a s 267

8. Nesnesel Tasarm iini yapyor diyebildiimiz nesne, demek ki tek o i iin yazlmtr. Halbuki s g s c s nesnesel yntemin gc, bir veri tanm etrafnda birok servisin salanabilmesidir. o u u c g Bu servislerin ill ki birbirlerini aryor ve birbirleri ile yakn alkada olacak a c g a hlde tasarlanm olmas gerekmez. Bu yzden bir classn metot listesi, bir a s u alveri listesine benzer denir. Deiik ihtiyalar iin deiik kalemler vardr1 . s s gs c c gs Mesel java.util.ArrayList classn rnek alrsak, d dnyaya salad a o s u g g birok servis vardr. add ars ile nesneye (listeye) bir eleman eklenmesini c c g salar, remove ile bir nesnenin silinmesi servisini salar. Carlar add ile remove g g g arasnda direk bir kod balants yoktur. Bu iki metot birbirlerini armazlar. g c g Ama ayn class uzerinde bulunurlar. Eer bu i iin sadece tek bir ilem iin g s c s c yazlm bir class kullansaydk, o zaman ListAdder ve ListRemover gibi iki s class yazmamz gerekecekti. Bu classlardaki metotlar ise doIt gibi komik bir isimde olabilecek bir tek metot olacakt. Tavsiyemiz, doIt metotlarndan ve bu metotlar ierecek classlardan kanmanzdr. c c Deiik servisler salayan bir nesne dunmek tasarmc iin faydaldr. Ayn gs g us c ekilde, bir sistem iinde ayn classtan gelen birok nesnelenin ayn anda, farkl s c c roller oynayabileceini (yni iki nesnenin deiik metotlarnn arlabileceini) g a gs c g g dunmek te tasarmc iin faydaldr. us c

Nesnesel Modellerde Tepe Fonksiyonu Yoktur! Prosedrel disiplinden gelen ve kurtulmamz gereken ikinci bir alkanlk, yazu s makta olduumuz uygulama iin srekli bir st nokta aramaktr. Ust nokg c u u tadan kastmz, uygulamada her eyin balad ve kontrol edildii o tek iletici, s s g g s arc, ana metot, balang noktasdr. Prosedrel gnlerden kalma bu alkanl, c g s c u u s g nesnesel sistemler kurarken terketmemiz gerekiyor, unk eer srekli ust nokta c u g u metotunu dunrsek, tasarmz ok fazla o kullanm iin olacak, ve kod us u c c dzeni asndan tm fonksiyonlarmz o balang koca metotunun uydusu u c u s c hline gelerek, en kt durumda balang metotunun olduu classta bir takm a ou s c g ek metotlar haline gelecektir. Nesnesel sistemlerde ust nokta yoktur. Nesnesel tasarmlarda uygu lama denen ey, tm classlar kodlandktan sonra en son aama olarak, son s u s anda gereken classlarn birletirilerek (arlarak) biraraya getirilmesi gereken s c g bir yapboz resmidir. Burada belki de en nemli fark, hangi eylemin hangisinden o nce geleceini vurgulayan bir ncelik farkdr. Prosedrel yntemler tasarmn o g o u o yukardan-aa (top-down) yaplmasn zorlarken, nesnesel yntemde tasarm s g o alttan yukar (bottom-up) doru gider. g
1 4.1 bl m nde bahsedilen Command mimarisinin bu kurala uymad dun lebilir, ou u g us u fakat Command mimarisindeki durum, teknolojik bir gereklilikten (network iletiim hznn s ayn JVMde olan iletiimden daha dun olmas sebebiyle) ortaya kmtr. Dediimiz gibi, s us c s g teknolojik snrlar mimariyi etkilemitir. s

268

Modelleme Ornek Bu dunce farkn herhalde en iyi ekilde bir rnek uzerinden aktarabiliriz. us s o Uygulamamzn amac u olsun: Bir sayy bir say dzeninden dierine tamak. s u g s Mesel, 2lik dzende 110010010 saysn, 10luk dzendeki karlna gitmemiz a u u s g gerekiyor. Ya da tam tersi ynde gidebilmemiz lazm. Her dzenden her dzene o u u geebilmeliyiz. c Prosedrel (functional) bir gemiten gelen programc, hemen bu noktada u c s ne yaplmas gerektiine odaklanr, ve o ust fonksiyonu dunmeye balard. g us s Onun bulmas gerekenler, verileri alan, ileyen fonksiyonlar olacakt, ve veriler s bir ilemden dierine aktarlrken yolda deie deie istenen sonuca ulalacakt. s g gs gs s Tasarm oyle olabilir. s
public static void main() { double fromNumber; double fromBase; double toBase; fromNumber = ...; fromBase = ...; toBase = ...; ... }

Iyi bir prosedrel programc olarak hemen ana metotu koyduk. Uygulama iin u c gereken girdileri burada zaten alyoruz. O zaman bu girdileri ne yapacamz g tasarlamamz gerekiyor. Hemen bir takm alt metotlar kodlamaya balyoruz. s Bir sayy bir dzenden dierine evirirken ara seviye olarak onluk dzene gitu g c u memiz gerekiyor, unk onluk dzenden dierlerine nasl geeceimizi biliyc u u g c g oruz. O zaman ilk nce, onluk dzene geen metotu armamz ve kodlamamz o u c c g gerekiyor.
public static void main() { String fromNumber; int fromBase; int toBase; fromNumber = ...; fromBase = ...; toBase = ...; int fromNumBase10 = convertToBaseTen(fromNumber); } public double convertToBaseTen(double fromNumber) { ... }

Sonra bu ele geen sayy, yeni dzene evirecek fonksiyona gndereceiz. c u c o g 269

8. Nesnesel Tasarm
public static void main() { String fromNumber; int fromBase; int toBase; fromNumber = ...; fromBase = ...; toBase = ...; int fromNumBase10 = convertToBaseTen(fromNumber); String toNumber = convertToBase(fromNumBaseTen, toBase); } public int convertToBaseTen(double fromNumber) { .. return numBaseTen; } public String convertToBase(int fromNumBaseTen, int toBase){ ... return toNum; }

Bu yntem olduka kalabalk bir koda sebebiyet verdi. Ozellikle ana metot o c daha programn banda neredeyse yaplabilecek her ary yapyor, ve tm s c g u gereken deerleri o hatrlyor. Bundan daha iyi bir tasarm yapamaz mydk? g Nesnesel tasarm deneyelim. Nesnesel yntemdeki prensipleri hatrlayalm. o Yukardan aa deil, aadan yukar gidiyoruz. Bunu yaparken tasarladmz s g g s g g metotlar, bir classn alveri listesi gibi gryoruz. Bir class, bir uygulama s s ou iinde birden fazla rol oynayabilir. O zaman uygulamada bu tanma uyan class c nedir? Bir say! Evet, bize gereken kendini onluk dzene, ya da kendini onluk u dzenden baka bir dzene evirebilecek olan, ve hangi say dzeninde olduunu u s u c u g kendi bilen bir say classdr. Bir say class, uygulama srasnda birok deiik c gs rol oynayabilir; Cevirilen rol oynayan bir nesne, kendini onluk dzenden gstere u u o bilecek, hedef roln oynayan nesne ise, hangi dzende olmas gerektiini bilen, u u u g ve evirim iin kendini nce onluk dzene, sonra gereken hedef dzene evirmeyi c c o u u c bilecek bir nesne olacaktr. Bu adan baklnca say class uzerindeki metotlar c bir alveri listesidir. Ust nokta dunmeden bu metotlar koyduk, yni uygus s us a lamamz artk tepe noktadan kontrol edilen bir ar zinciri deil, iki nesnenin c g g rol ald bir simulasyon hline geldi. Kodu yazalm: g a
public class Number { String value; int base; public Number(String value, int base) { }

270

Modelleme

public Number(int base) { } public int toBaseTen() { .. return numInTen; } public String getValue() { return value; } public void convert(Number from) { // // Cevirilecek say: from.toBaseTen() // Hedef: this.base // } }

Grdumz gibi kodlama asndan neredeyse ayn olan metotlar doru class o ug u c g uzerinde gelince isimleri daha temiz hle geldi. Hangi dzende olduunu bilen a u g bir nesneye convert ars gelince ve parametre olarak bir dier Number nesc g g nesi verilince bunun anlam ok nettir; Parametre olarak gelen Numberdaki say c dzeninden kendi iimizde tuttuumuz say dzenine gemek istiyoruz. u c g u c Ayrca bu yeni tasarmda, evirilecek ve hedef saylar hakkndaki bilgic leri ana metotta duran deikenlerde tutmamz gerekmiyor. Her class, kendisi gs hakknda bilgileri kendi tutacaktr. Bunlar, say deeri ve hangi say dzeninde g u olunduudur. g Bu yeni tasarm kodladktan sonra, en son olarak ana metotu kodlayabiliriz. Ana metotun ne kadar daha temiz olduunu greceiz. g o g
public class App { public static void main(..) { Number from = Number(..,..); Number to = Number(..); to.convert(from); System.out.println(to.getValue()); } }

271

8. Nesnesel Tasarm Grldu gibi evirilecek say, hangi dzende olduu bilgisiyle beraber, from o u ug c u g referansyla eriilen Number nesnesi iinde tutulmaktadr. Hedef say dzeni, s c u to referans ile eriilen Number iinde tutulmaktadr. Say deeri ve dzeni, bes c g u raber, ayn modl iinde durmaktadrlar, ve bu durum ana modl rahatlatm, u c uu s ve genelde kod bakm asndan bir ilerleme salamtr. c g s Dier bir ilerleme, convert adl metota hedef saynn bir Number parameg tresi olarak gelmesidir. Eskiden String ve int tipinde deerler geliyordu, ve g bu basit tiplere bakarak neyin ne olduu tam anlalamyordu. Yeni yntem g s o sayesinde daha ust seviyede olan Number tipleri metottan metota gnderilmek o tedir, ve bu da kodun anlalrl asndan iyidir. s g c

8.3

Tasarm D zenleri (Design Patterns) u

Nesnesel dillerin programcya salad belli silahlar/yetenekler (capabilities) g g vardr. Bu yetenekler nesnesel yntemin tabiatndan gelirler, mesel okyzllk o ac u uu (polymorphism) ve miras alma (inheritance) yeteneklerinin standart rnei, ust o g seviye bir classtan miras alan alt seviye gerek (concrete) classlarn, ust sec viye referans uzerinden eriilmesi rneidir. Bu kullanmda, mesel, ayn List s o g a uzerinde ayn ust seviye tipinde ama gerek tipi deiik alt tiplerde olan nes c gs nelerin rnei gsterilebilir. Tm bu alt tipte nesneler uzerinde, ust seviyedeki o g o u bir metot alta okyzllk ile intikal etmitir, ve bu metotun gerekletirimi c u uu s c s her alt tipte deiik olmas sebebiyle, ust seviye tip uzerinde yaplan arlar, gs c g deiik davranta bulunurlar. Bu kullanm, ufak apta bir tasarm dzenidir. gs s c u Bu tasarm dzenini kullanan bir uygulama rnei yle olabilir: Ekranda u o g so ugen, ember ve poligon izmeye izin veren bir izim programn dunn. c c c c us u Mouse ile tkladmz noktada, hangi gr modundaysak (Circle, Triangle, g u Polygon), o gr, o noktada, o nesnenin draw metotu uzerinden izilecektir. u c Buna ek olarak izim program, ekran yenile komutuna hazr olmak iin c c ekrandaki grlerin bir listesini tutmaldr. Bylece ekrana tekrar iz (reu o c fresh) komutu verildiinde, herey silinip tm grler uzerinde tekrar draw g s u u metotu arlabilecektir. List nesnesini tayan Screen (ekran) nesnesi, o c g s listeyi tekrar gezdiinde, listedeki elemanlar Figure tipine dntrmesi (cast) g o us u yeterlidir. Cunk Figure uzerinde draw interface metotu tanmldr, ve okyzllk u c u uu kanunlarna gre Figure tipi uzerinden baktmz bir nesnenin draw metotunu o g armak iin o nesnenin gerek tipine inmemiz gerekmez. Nesnesel yntem, c g c c o draw arsn gerekli koda otomatik olarak gtrecektir. Bylece alttaki kod c g ou o paras c
for (int i = 0; i < figureList.size(); i++) { Figure figure = (Figure)figureList.get(i); figure.draw(); }

ile tm grleri tekrar izmemiz mmkn olacaktr. u u c u u 272

TASARIM DUZENLERI Demek ki tasarm dzenleri, baz seviyedeki nesnesel teknikleri kullanarak, u deiik ekillerde birletirerek oluturulmu ust seviye tekniklerdir. Nesnesel gs s s s s tekniklerin ve dillerin anlatld her kitapta aslnda tasarm dzenleri de bir g u yandan anlatlmaktadr, sadece en direk ve dil zelliini en basite vurgulayacak o g c olan eitleri n planda olmaktadr. c s o

8.3.1

Kullanlan D zenler u

Gamma ve arkadalarnn kard Tasarm Dzenleri [2] adl kitap, yazarlarnn s c g u projelerinde ust uste kulland ve temel kullanmlardan daha deiik kodlama g gs ve tasarm dzenlerini dnyaya tantmtr. Bu kitaptaki teknikler bir yana, bir u u s tasarm dzeninin nasl bulunup ortaya konulacan ortaya koymas asndan u g c kitap daha da faydal olmutur. Kurumsal programclar iin yapmamz gereken s c tek uyar, bu kitaptaki paylalan tasarm numaralarnn pr dil seviyesinde ols u masdr (ve kurumsal uygulamalarda d teknolojinin nemini artk biliyoruz). s o Tasarm Dzenleri kitabndaki zmlerin neredeyse tamam ayn JVM, yerel u co u metot ars ngrsyle yazlm tekniklerdir. Kurumsal yazlmlarda ie c g o ouu s s yarayan Gamma TD teknikleri altta grlebilir: ou Command Template Method Facade Singleton

Figure
has +draw()

Screen
+figureList: ArrayList +refresh()

Circle
+center +radius +draw()

Polygon
+topLeft +topRight +bottomRight +bottomLeft +draw()

Triangle
+p1 +p2 +p3 +draw()

Sekil 8.6: Sekiller Nesne Diyagram 273

8. Nesnesel Tasarm Bu dzenleri ksaca aklayalm (Command dzeni haricinde, unk bu dzen u c u c u u 4.1 blmnde ayrtntsyla anlatlmtr). ou u s

Template Method

SuperClass
+algorithm() +methodA() +methodB() +methodC() void algorithm() { ... methodA(); .. methodB(); methodC(); }

SubClass1
+methodC()

Sekil 8.7: Template Method Nesne Tasarm

Arasnda miras ilikisi olan ust ve alt class tiplerini kodlarken, ileride yeni s eklenebilecek alt class tiplerine yarayacak olan metotlarn ust classa ekilmesi c gerekir. Bu metotlar, bylece her yeni alt class tarafndan paylalabilmi olao s s caktr. Ortak metotlar ust classa koyduumuzda, bazen, kodun iinde genel ol g c mayan ve her class iin deiik olmas gereken bir blm gzmze arpabilir. c gs ou o u u c Eer byle bir blm mevcut ise, tm metotu tekrar aa, alt classa doru g o ou u s g g itmeden, Template Method dzenini kullanabiliriz. Bu dzene gre, her alt u u o classta deiik olabilecek ufak kod paras ayr bir metot iine konarak, ust gs c c tipte soyut (abstract) olarak tanmlanr. Bylece alt classlar bu metotu tanmlamaya o mecbur kalrlar. Ve alt classtaki zel blm tanmlama/kodlamas yaplr yaplmaz o ou ust classtaki metotlar genel blmlerini iletip, zel blm iin alt snftaki ou s o ou c metota ileyii devredebilirler. Bundan kendilerinin haberleri bile olmaz, unk ons s c u lar kendi seviyelerindeki abstract metotu armaktadrlar. c g Template Method, ust seviyede bir metot iskeleti tanmlayp alt classlara sadece ufak deiiklikler iin izin verilmesi gerektii durumlarda kullanldr. gs c g s 274

TASARIM DUZENLERI Facade Bir zellii iletmek iin birok nesneyi ard ardna armak gerekiyorsa, zelo g s c c c g o lik kullanmn tek bir giri classna alarak arka plan arlar giri classna s c g s yaptrmak faydal olabilir. Tasarm Dzenleri kitabnda bu giri classna Fau s cade ad veriliyor. Facaden faydas, karmakl azaltarak bir sistemin d s g s dnyaya gsterdii arayz basitletirmeyi amalamasdr. Mesel Sekil 8.8 u o g u u s c a uzerinde gsterilen nesne modeli javac gibi bir derleyici (compiler) sistemin o tasarm modelidir. Bu modelde grldu gibi birok i yapan classlar mevo u ug c s cuttur. Fakat dardan balanan iin bu alt seviye nesneleri yaratp teker teker s g c armak art deildir, dars iin tek giri nesnesi olan Compiler kullanmak c g s g s c s hem kullanm, hem de kod bakm asndan daha rahat olacaktr. c Singleton Uygulamamzda bir classtan sadece bir nesne olsun istiyorsak ve bunu mimari olarak kodu kullanan her programc uzerinde zorlamak istiyorsak, o zaman Singleton dzenini kullanabiliriz. Bu dzene gre Singleton olmasn istediimiz u u o g classn ilk nce kurucu metotunu (constructor) Java private komutu ile dardan o s saklarz. Bylece kurucu metot sadece classn kendisi tarafndan kullanlr olur. o Bunu yapmazsak herkes class istedii gibi alp birden fazla nesnesini kullang abilirdi. Kurucu metotu sakladmz iin, bir yaratc metotu bir ekilde salamak g c s g zorundayz. Singleton classlarnda bu metot tipik olarak instance adnda bir

Sekil 8.8: Facade 275

8. Nesnesel Tasarm yaratc metot olur. Bu metot, static olmaldr unk Singleton classndan c u hlen tek bir nesne bile mevcut deildir ve ilk arlabilecek metot bu yzden a g c g u static olmaldr. Bu metot, gerek nesneyi static olan dier bir private c g deiken uzerinde arar/tutar, buna uniqueInstance (tekil nesne) ad verilebilir. gs Eer uniqueInstance uzerinde bir nesne var ise, o dndrlr, yok ise, bir g o u uu tane yaratlp dndrlr. Once mevcudiyet kontrol yapld iin nesnenin bir o u uu u g c kez yaratlmas yeterli olmaktadr, ilk new kullanmndan sonra Singletondan geriye gelen nesne hep ayn olacaktr.

8.3.2

s POJOlar ve Ilem Mant g

Kalclk arac Hibernate, ya da dier POJO bazl teknolojileri kullanrken, bir g modelleme tavsiyesini aklmzda tutmalyz; POJOlar dier classlar gibi bir g classtrlar, uzerlerine get ve set haricinde etrel, ilem mant metotlar ve c s g fonksiyonlar konulmasnda bir zarar yoktur. Htta daha ileri giderek bunu yaplmasn iddetle tavsiye edeceiz. Son zaa s g manda popler olan veri, uzaktan nesne ars yapma teknolojilerinin POJO u c g bazl olmaya balamas ile oluan bir izlenim, POJOlarn aptal bir ekilde s s s braklp sadece veri transferi iin kullanlmaya balanmasdr. Buna hi gerek c s c yoktur unk bir eer bir POJO, uygulamamzn verisini tutan yer ise ve c u g bir class, (nesnesel modelleme asndan) veriler ve ilemleri birarada tutan c s bir birim ise, o zaman ilemlerimizi POJOlardan ayrp bambaka bir ilem s s s s class iine gmmemize gerek kalmayacaktr. Ilemimiz bir POJO iindeki c o c veriyi kullanyor ve modelleme asnda bu temiz bir sonu veriyor ise, ilemin c c s POJO class iine koyulmasnda hibir saknca yoktur. c c

8.3.3

Dier D zenler g u

Gamma ve arkadalarnn Tasarm Dzenleri kitabndaki dzenlerin pek aznn s u u kurumsal uygulamalar iin faydal olmasna ramen tasarm dzenleri kavram, c g u

Singleton
+uniqueInstance +instance() +methodA() +methodB() public static Singleton instance() { if (uniqueInstance == null) { uniqueinstance = new Singleton(); } return uniqueInstance; }

Sekil 8.9: Singleton 276

MIMARI bir prensip ve dunce sistemi olarak yazlm dnyas iin faydaldr. Hatta us u c sylenebilir ki matematiksel baz olmayan yazlm mhendisliine disiplinli o u g ve metodik bir ekilde yaklamak isteyenler iin tasarm dzenleri ve ileyen s s c u s yntemler (best practices), neredeyse izlenebilecek en formele yakn yntemo o lerdir. Bu balamda, okuduunuz bu kitap bize gre faydal tasarm dzenleri g g o u ve ileyen yntemlerin toplamdr. Fakat bu kitapta Gamma kitabna kyasla s o daha d teknolojiye yakn tasarm dzenleri sunulmaktadr. Bu sebeple bus u radaki tasarm dzenleri mimari(architecturel) zmler kategorisine girebileu co u cek tavsiyelerdir. Bunun sebepleri bizim ahsi proje tecrbemize dayanyor; s u Tasarm Dzenleri kitabnn neredeyse her kelimesini dikkatle izlediimiz ve u g yine de birok badire atlattmz bir projemizin sonunda teknik liderimiz ve c g arkadam Jim DAugustine yaknarak yle demiti: Bize tasarm dzenleri s so s u deil, mimari dzenler lzm! g u a Son olarak, Kar Dzen (Anti Pattern) akmndan bahsedelim. Kar Dzens u s u ler, norml tasarm dzenleri aksine ne yaplmas gerektiini deil, ne yaplmamas a u g g gerektiini tavsiye ederler. Orneklerden bir tanesi DTO (Data Transfer Obg ject) kar dzenidir; Bilindii gibi DTO tekniini kullanlar, servis tarafndan s u g g yaplacak her transfer iin sadece get/set metotlarndan oluan bir veri class c s (Hibernate buna POJO diyor) yazmay salk verir. DTO kar dzeni DTO s u classlarnn gereksiz olduunu sylemektedir. Buna biz de katlyoruz, unk artk g o c u Hibernate gibi modern yaklamlar sayesinde veri alveriinin tamamen POJOlar s s s uzerinden olduu iin, ek veri transfer classlarna gerek kalmamtr. Servis g c s taraf ve veri taban arasnda kullanlan nesneler, byk bir rahatlkla baka u u s yerlere veri transfer etmek iin de kullanlabilirler. (Tarihi olarak insanlar DTO c kullanmna herhalde Entity Beanlerin hantal yaps yznden mecbur olmutu, u u s fakat Entity Beanler artk teknik olarak emekli edildiine gre, DTOya olan g o ihtiya ta ortadan kalkmtr). c s

8.4

Mimari

Nesnesel tasarmda birka class ieren bir tasarm, nokta vuru zm yni c c s co u u a ufak apta bir tasarmdr. Bu teknikler uygulamann ufak bir blmnnn c ou u u u zm iin kullanlan nesnesel numaralardr. Fakat uygulamadaki tm zellikco u u c u o lerin kodlanmas iin baz genel kurallar koyan bir alt tabaka olmas arttr. Bu c s tabaka baz kodlama kalplarnn ieren ve programclarn miras almas gereken c bir ust class, ya da arlmas proje teknik lideri tarafndan herkese duyu c g rulmu olan yardmc classlar toplam olabilir. Literatrde bu ekilde genel s u s kurallar koyan classlarn ve kod paralarnn toplamna mimari diyoruz. Eer c g StrutsHibAdv rnek projesini dunrsek, bu projenin mimarisini yle tarif o us u so edebiliriz: Tm Hibernate ilemlerinden nce Session almas, ve transu s o c action balatlmas HibernateSession yardmc class uzerinden s 277

8. Nesnesel Tasarm yaplacaktr. Tm Struts Actionlar org.mycompany.kitapdemo u .actions altnda olacak, ve her sayfa header.inc dosyasn kendi kodlar iine en tepe noktada dahil edecektir. Basit veri erisimi c haricinde sorgu ieren tm veri eriim ilemleri, bir DAO kullanc u s s maya mecburdur; Mesel Car arlkl sorgular iin CarDAO kula g c lanlmas gibi. Her DAO, kurucu metotu iinde bir Hibernate transacc tion balatmaldr, ama commit DAO commit yapmayacaktr. Struts s Actionlar da commit yapamazlar. Commit yapmak, bir Servlet ltresi olan HibernateCloseSessionFilternin grevidir, ve bu lo tre her .do soneki iin yine herkesin kulland web.xml iinde aktif c g c edilmitir. Ayn ltre, Session kapatmak, ve hata (exception) var s ise, o anki transaction rollback etmek ile de ykmldr. u u u u Grldu gibi bu kurallar projedeki her programcnn bilmesi gereken kuo u ug rallardr. Projeye ortasnda katlan bir programc, hemen bir Struts Action yazmaya balayp iine alnen bir takm JDBC kodlar yazarak veri tabanna s c a erimeye almayacaktr. Bu projenin kurallarna, mimarisine gre, Struts Acs c s o tionda HibernateSession uzerinde alan Session ile, Hibernate yntem c o leri uzerinden veri tabanna eriilecektir. Yine ayn kurallara gre yeni pro s o gramc commit, ve close arlarn elle yapmaktan men edilmitir. Projenin c g s mimarisi, bu arlar merkeziletirmi, ve kodun geneline bu ekilde bir temic g s s s zlik salamtr. Yeni gelen programcnn bu kural takip etmesi beklenecektir. g s Bu ekilde tarif edilen mimarilerin, kod temizlii asndan olduu gibi, s g c g proje idaresi ynnden de etkileri olduunu anlamamz gerekiyor. Bir mimari o u g balamnda baz kurallarn konulmas ve baz kullanmlarn merkeziletirilmesi g s demek, uygulamamzda nce bitmesi gereken parann mimari ksm olduu o c g sonucunu getirir. Proje idaresi asnda mimari, kodlama asndan seri urec c time gemeden nce bitmesi gereken eydir. Eer seri uretimden kan her c o s g c urn bir zellik olarak dunrsek, mimari de fabrika olacaktr. Tabii bu u u o us u analojiyi dikkatli anlamak gerekiyor, sonuta iler hldeki bir program da bir c s a fabrika gibi grlebilir; Bizim burada bahsettiimiz programn ileyii deil, o ou g s s g programn kodlama aamasnda programclarn kodlama eforudur. s Proje idaresi bakmndan mimarinin nce bitmesine kar bir argman, o s u mimarinin zellikler kodlanrken bir yan urn olarak kendi kendine kmas o u c beklentisidir; Fakat eer mimari kod temizlii, hata azaltm gibi getirmesi g g asndan nemli ise, nceden mevcut olmas gereken bir kavram olduu orc o o g tadadr. Bir mimariyi projenin ortasnda kodlarmza sonradan empoze etmeye karar vermisek, bu durum mevcut olan kodlar uzerinde yaplmas gereken s byk bir deiiklik anlamna gelebilir, ve bu deiiklik iin harcanacak efor, o u u gs gs c teknik ilerlemenin getirecei herhangi bir avantaj silip yokedebilir. Bu sebeple g mimarinin projenin banda hazr olmas nemlidir. s o Mimariyi tasarlamak, her projede teknik liderin grevidir. Ayrca mimari o ortaya kartldktan sonra kurallarn takip edildiinin kontrol de teknik lider c g u uzerinde olacaktr. Oyle ki, proje bittiinde tm kod baz sanki tek bir kii g u s 278

MIMARI yazm gibi gzkmelidir. Iyi bir mimari kodda tekrar azaltacak, kullanm s o u kalplarn ortaya koyarak yeni katlan programclara yn gsterecek ve hata o o yapma ihtimallerini azaltacaktr. Mimari nceki projelerde alnan dersleri de o yanstan bir kurallar toplamdr. Bunun haricinde her zellii (functionality) kodlayan programc kendi istedii o g g gibi kodlamakta serbesttir. Tasarm dzenleri ile mimari arasndaki iliki yledir: Mimarimizin bir u s so ksm iinde bir tasarm dzeni bir kural olarak ortaya kabilir. Ornek olarak c u c 4.1 blmnde tarif edilen mimari, Command tasarm dzeninin her uzaktan ou u u nesne eriim gerektiren durum iin kullanlmasn mecbur klm, bylece bir mis c s o mari seim hline gelmitir. Fakat bir tasarm dzeni hibir mimarinin paras c a s u c c olmadan, tek bir zellik iin kendi bana da kullanlabilir. Ksacas mimari o c s genelde birok kiiyi etkileyen, ve genel olan bir kavramdr. c s

279

8. Nesnesel Tasarm

280

Bl m 9 ou

Veri Tabanlar

Bu Bl mdekiler ou s Ilikisel Teori ve Kavramlar Indeksler, Grntler, Tetikler ou u Oracle, PostgreSQL ve MySQLi Unix uzerinde kurmak

281

9. VERI TABANLARI er kurumsal uygulamann etrafnda dndu, bir depoya alp verdii, o ug g sorgulayp bulduu ve biriktirdii metin ve saysal bilgilerin toplamna g g veri diyoruz. Bir kurumsal uygulamada veriye eriim, en hayati noktalars s dan biridir. Iyerleri verilerinin doruluuna ve btnlune ok nem verirler. g g u u ug c o Htta kitabmzn konusu olan kurumsal uygulamalar iin denebilir ki, aslnda a c bir uygulamann yegne grevi veri tabanndaki veriyi gze gzel bir ekilde a o o u s sunmaktan ve gze gzel gelen ekilde almaktan ibarettir. o u s Veri depolama ve geri almann modellerinden biri olan ilikisel model, E. s F. Codd [9] tarafndan ortaya srlm ve gnmzdeki modern tm ilikisel u u us u u u u s veri tabanlarn ileyiini tanmlayan bir teorik altyapdr. Bu modelin temeli s s kme teorisine dayanr, ve tamamyle tanml, i btnlu kurulmu salam u c u u ug s g matematiksel bir yapdr. Yap yledir ki, bir ilikisel model uzerinde ileyen bir o s s sorgunun doru olup olmadn bile matematiksel olarak ispatlayabilirsiniz1 . g g s Ilikisel model, ortaya atld 70li yllarda, akademik evrelerde mthi bir g c u s arpmaya sebebiyet vermiti. O vakitte yarta olan dier veri modeli olan c s s s g hiyerarik model, ilikisel model ile girdii arpmadan yenik ayrlmtr2 . s s g c s s Akabinde ilikisel modeli ticari urn hline getiren ve SQLi ilk destekleyen s u a irketlerden olan Oracle, bu alana ok hzl girmesiyle mthi bir piyasa hakimiyetine s c u s u ve nansal baarya kavumutur. Onyze odakl olan Microsofttan sonra bir s s s servis taraf teknolojisi satcs olan Oraclen ikinci byk yazlm irketi olu u s mas, veri depolamas ve eriiminin nemine iaret etmektedir. s o s Gnmzde artk SQL dili ile eriilen ilikisel veri tabanlar, ticariden ak u u u s s c yazlma, kukten bye giden geni bir yelpazede bulunabilen hale gelmilerdir. uc u ug s s Gnmzde eer nans, telekom, salk sektrnden biri iin bir kurumsal u u u g g ou c yazlm gelitiriyorsak, arka plandaki veri tabann olarak ilikisel bir teknoloji s s bulmamzn olasl artk ok yksektir. g c u Verinin depolama ve eriimin bu seviyede nemi sebebiyle, verinin tutulduu s o g ilikisel veri tabanlarn, ilikisel emalarn altyapsn tanmlayan ilikisel mods s s s eli, ve tm teori ve teknolojinin bir araya geldii SQL eriim dilini reneceiz. u g s og g

9.1

s Ilikisel Model

s Ilikisel modelin temeli, birden fazla kolonu birarada tutarak onlar arasnda bir s alak kurulmasn salayan iliki kavramdr [10, sf. 138]. Iliki, modern veri taa g s banlarnda bir tabloya tekabl eder. O zaman bir tabloda, yni bir ilikide, tipik u a s olarak birden fazla kolon olur. Tablo 9.1 uzerinde rnek bir iliki gryoruz. o s ou Eer bir tabloya veri eklemek istiyorsak, o tablonun iliki yapsna uyan g s verileri SQL ile veri tabanna verebiliriz. Bunun iin SQLde INSERT komutunu c kullanabiliriz. Ornek bir INSERT ibaresi altta gzkmektedir. o u
ekilde bir analiz ne yazk ki yazlm m hendislii gibi alanlarda m mk n olmas u g u u maktadr, unk bu alanlardaki eya makina deil, insandr c u s g 2 Nesnesel veri tabanlar da hiyerarik modelin g n m zdeki yansmalardrlar, ve bir s u u u t rl sektrde kabul grmemelerinin sebebi, 70lerdeki sava kaybetmi olmalarnn bir sonuu u o o s s cudur
1 Ayn

282

ILISKISEL MODEL Tablo 9.1: Ornek Tablo (Car)


LICENSE PLATE DESCRIPTION

Tablo 9.2: Ornek Tablo (Veri Ile)


LICENSE PLATE DESCRIPTION

34 34 35 16

TTD 2202 GD 22 TG 54 RR 344

33 RE 43

sar araba krmz araba benim tarim bu araba ikinci el sar araba

INSERT VALUES INSERT VALUES INSERT VALUES INSERT VALUES INSERT VALUES ..

INTO (34 INTO (34 INTO (35 INTO (16 INTO (33

CAR (LICENSE_PLATE, DESCRIPTION) TTD 2202, sar araba); CAR (LICENSE_PLATE, DESCRIPTION) GD 22, krmz araba); CAR (LICENSE_PLATE, DESCRIPTION) TG 54, benim tarifim); CAR (LICENSE_PLATE, DESCRIPTION) RR 344, bu araba ikinci el); CAR (LICENSE_PLATE, DESCRIPTION) RE 43, sar araba);

Bu komut, CAR adl tabloya be satr veri ekleyecektir. Komut iledikten sonra s s sonu, Tablo 9.2 uzerindeki gibi gzkecektir. CAR tablosundan veri almak iin, c o u c SQLin SELECT komutu kullanabiliriz.
SELECT * from CAR;

komutu, CAR arabasndaki tm verileri ve tm kolonlar (* iareti ile) geri geu u s tirir. Eer geri getirilen veriler uzerinde (satr baznda) ltreleme yapmak isg tiyorsak, SELECT komutuna WHERE komutunu eklemek zorundayz. Mesel a
SELECT * from CAR WHERE LICENSE_PLATE=34 TTD 2202

komutu, plakas 34 TTD 2202 olan tm arabalar (yani tek satr) geri getireu cektir. Bir tablodaki veriyi gncellemek iin, UPDATE komutunu kullanmamz gerekir. u c UPDATE, gncellenmek istenen verinin yeni hlini set komutundan sonra alr. u a Gncelleyecei satrn hangisi olacan ise WHERE komutuna verilen bir ltre u g g deeri ile anlar. g
UPDATE CAR set DESCRIPTION = siyah araba WHERE LICENSE_PLATE = 34 TTD 2202

283

9. VERI TABANLARI Tablo 9.3: Garage Tablosu


ID DESCRIPTION

1 2

Garage 1 Garage 2

Tablo 9.4: Yeni Car


LICENSE PLATE DESCRIPTION GARAGE ID

34 34 35 16

TTD 2202 GD 22 TG 54 RR 344

33 RE 43

sar araba krmz araba benim tarim bu araba ikinci el sar araba

1 1 2 2 2

Bylece daha nce sar araba olan tanm (description) UPDATE komutundan o o sonra siyah araba hline gelecektir. a

9.1.1

s Tablo Aras Ilikiler

s Ilikisel modelde kolonlarn arasnda iliki kurulduu gibi (bir tablo), tablos g lar arasnda da iliki kurmak mmkndr. Bunu yapmak iin ilikisel model, s u u u c s yabanc anahtar (foreign key) kavramn kullanr. Yabanc anahtar, bir tablodaki asal anahtar, kimlik nitelii tayan bir kolonun, dier bir tabloya bir g s g iaret edici olarak konmasdr. Mesel Tablo 9.3 uzerinde gsterilen yeni tabloya s a o iaret etmek iin, bu tablodaki bir satr (garaj) tekil olarak seebilen bir kolon s c c deerini (ID), iaret eden tablonun uzerine yabanc anahtar olarak (GARAGE_ID g s kolonu) koyarz (Tablo 9.4). Bu ilikinin kubak grnts Sekil 9.1 uzerinde s s s ou uu grlmektedir. ou

GARAGE
+ID +DESCRIPTION

CAR
+LICENSE_PLATE +DESCRIPTION +GARAGE_ID

s Sekil 9.1: Garage ve Car Ilikisi

284

ILISKISEL MODEL B t nl k Kontrolleri u u u Iki tablo arasnda yabanc anahtar ilikisi var ise, iaret eden tabloya bir veri s s eklerken, yabanc anahtarn iaret ettii dier tablodaki satrn mevcut olmasn s g g kontrol etmek, iyi bir prensip saylr. Mesel, sisteme bir CAR ekliyorsak ve bu a sistemin i kurallar balamnda bir arabann her zaman bir garaj altnda ols g mas gerektiini biliyorsak, o zaman CAR tablosu uzerindeki garage_id kolonu g uzerinde bir btnlk kontrol (integrity constraint) koyabiliriz. uu u u Btnlk kontolleri, bizim belirttiimiz bir kolon ve hedef kolon uzerinde, uu u g her veri eklendiinde veri taban tarafndan yaplan kontrollere verilen isimdir. g Bu kontrollere gre eklenen yabanc anahtarn deeri, iaret edilen tablodaki o g s asal anahtar iinde olup olmad kontrol edilir; Eer bu veri yok ise, veri taban c g g INSERT komutunuza bir hata mesaj ile cevap verecektir. Btnlk kontrolleri uu u koymak iin MySQL tabannda u komutu kullanabilirsiniz. c s
alter table car add FOREIGN KEY (garage_id) REFERENCES garage(id);

Dier tabanlarda szdizim farkl olabilir, fakat ii znde bilmeniz gereken, kayg o s o u nak ve hedef tablo+kolon ikilisini bilmektir. Yukardaki btnlk kontrol kouu u u mutu iletildikten sonra, artk car.garage_id kolonuna koyulacak her verinin s garage.id kolonunda olmas mecbur olacaktr. Birletirim s Iki tablo arasnda ilikiyi kurduktan sonra eer bir tablodaki satrdan, o satrn s g ilikisini olduu dier tablodaki satra atlamak istersek, ilikisel modelde birletirim s g g s s (join) kavramn kullanmamz gerekir. Birletirim, kme teorisinden gelen bir s u kavramdr, ve SQLde u ekilde gsterilir. s s o
SELECT * FROM GARAGE, CAR;

Bu komut, her iki tablodaki her satr dier tablodaki dier her satr ile teker g g teker kombinasyona sokarak, bir kartezyen kombinasyonu olarak geri getirir. Birletirime sokulan her tablo, FROM ibaresinden sonra birbirinden virglle s u ayrlarak belirtilmelidir. Eer CAR tablosunda 5, GARAGE tablosunda 2 satr g var ise, kartezyen birleim 10 tane satr geri getirecektir. Kartezyen birleim s s sonucunu Tablo 9.5 uzerinde gryoruz. ou Fakat bu birleim, hibir pratik uygulama iin faydal olmayacaktr. Geri ges c c len sonu listesini bir ekilde daraltmamz gerekmektedir. Counlukla ihtiyacmz c s g olan, balang tablolarndaki bir tablodan (ve onun bir satrndan) bir dierine s c g (onun bir satrna) atlayabilmektir. O zaman, kartezyen sonuta yabanc anahtar c ve asal anahtar birbirine uyan satrlar bu byk birleimden ekip kartmay u u s c c deneyebiliriz. Cunk, grdumz gibi, artk yabanc anahtar ve tekil anahtar u o ug u lar, ayn byk tablo iinde yanyana gelmilerdir, ve basit bir WHERE art, u u c s s birbirine uyan satrlar ekip karmak iin yeterli olacaktr. c c c
SELECT *

285

9. VERI TABANLARI Tablo 9.5: Kartezyen Birleimi s


ID DESCRIPTION LICENSE PLATE DESCRIPTION GARAGE ID

1 2 1 2 1 2 1 2 1 2

Garage 1 Garage 2 Garage 1 Garage 2 Garage 1 Garage 2 Garage 1 Garage 2 Garage 1 Garage 2

34 TTD 2202 34 TTD 2202 34 GD 22 34 GD 22 35 TG 54 35 TG 54 16 RR 344 16 RR 344 33 RE 43 33 RE 43

sar araba sar araba krmz araba krmz araba benim tarim benim tarim bu araba ikinci el bu araba ikinci el sar araba sar araba

1 1 1 1 2 2 2 2 2 2

Tablo 9.6: Filtrelenmi Kartezyen Birleimi s s


ID DESCRIPTION LICENSE PLATE DESCRIPTION GARAGE ID

1 1 2 2 2

Garage 1 Garage 1 Garage 2 Garage 2 Garage 2

34 TTD 2202 34 GD 22 35 TG 54 16 RR 344 33 RE 43

sar araba krmz araba benim tarim bu araba ikinci el sar araba

1 1 2 2 2

FROM GARAGE, CAR WHERE ID = GARAGE_ID;

Sonucu Tablo 9.6 uzerinde gryoruz. Filtrelenmi kartezyen kombinasy ou s onundan gelen bu ekilde sonular, daha pratik uygulamas olabilecek trden s c u sonulardr. Garajlar ve onlarn altnda olan arabalar, artk ayn satrda yanyana c hlde gsterilmitir. Eer daha da detayl bir sonu grmek istersek, mesel a o s g c o a 286

ILISKISEL MODEL Tablo 9.7: Tek Garajn Altndaki Arabalar


ID DESCRIPTION LICENSE PLATE DESCRIPTION GARAGE ID

1 1

Garage 1 Garage 1

34 TTD 2202 34 GD 22

sar araba krmz araba

1 1

sadece 1 nolu garaj altndaki tm arabalar grmek istersek, ustteki sorguyu u o biraz daha genileterek yle bir SQL kullanabiliriz. s so
SELECT * FROM GARAGE, CAR WHERE ID = GARAGE_ID AND GARAGE_ID = 1

Bu sorgunun sonucu Tablo 9.7 uzerinde sergilenmitir. Artk sadece 2 nolu ve s altndaki arabalar listemizde grmekteyiz. o Eer geri getirilen kolonlar (satrlar deil) ltrelemek istiyorsak, SELECT g g komutundan sonra belirtilen kolon listesi ile bu isteimizi belirtebiliriz. Orneimizde, g g * iaretini kullanarak tm kolonlar almak istediimizi belirttik, fakat SELECT s u g LICENSE_PLATE ile sadece plaka nolarn almamz mmkn olabilirdi. u u Coka ok trden ilikiler kurmak iin iki tablo arasnda bir ara tablo kullan c u s c may seebilirsiniz. Bu durumda iliki, Sekil 9.2 uzerindeki gibi gzkecektir. c s o u
GARAGE
+ID +DESCRIPTION

CAR
+LICENSE_PLATE +DESCRIPTION

GARAGE_CAR
+GARAGE_ID +LICENSE_PLATE

s Sekil 9.2: Ara Tablo ile Iliki Ara tabloyu birletirime dahil etmek iin, FROMdan sonra gelen listeye, ara s c tabloyu da eklemeniz gerekecektir. Bunun yapmann genel mant, iki tablolu g kullanm ile ayndr.
SELECT * FROM GARAGE, CAR, GARAGE_CAR WHERE ID = GARAGE_ID AND

287

9. VERI TABANLARI
CAR.LICENSE_PLATE = GARAGE_CAR.LICENSE_PLATE AND GARAGE_ID = 1;

Bir Tabloda Olan, Otekinde Olmayan Satrlar Iki tabloda birbirine uyan satrlar birletirim (join) ile getirmek mmkndr. s u u u Eer bir tabloda olan ama bir dierinden olmayan satrlar geri getirmek isg g tersek, SQLin WHERE NOT EXISTS komutunu kullanmamz gerekecektir. NOT EXISTS, her zaman bir alt sorgu (subsquery) iinde kullanlr. Alt sorgular, c SQL sorgularnz daha detaylandrmak iin kullanlan tekniklerden biridir; Bu c teknik ile ana sorgudan sonra parantezler iinde ust sorgudaki kme iinden c u c daha detayl seimler yapmak mmkndr. c u u u Alt sorgular, ou durumda, bir birletirim formuna evirmek mmkndr. c g s c u u u Fakat sektrmzde genel kullanm birletirim ile zlebilecek problemlerin diou u s co u rek birletirim kullanlarak zlmesi ynnde olduu iin, alt sorgular birletirim s co u o u g c s szdizimi kadar rabet grmemitir; NOT EXISTS kullanm bunun haricindedir, o g o s unk standart SQL balamnda bir satrda olan ama tekinde olmayan sonular c u g o c bulma sorgusunu daha temiz bir ekilde gerekletirmenin yolu alt sorgular s c s uzerinden NOT EXISTS komutunu kullanmaktan geer. c NOT EXISTS kavramn anlatmak iin bir rnek gelitirelim: Bu rnekte iki c o s o tablo yaratalm, passengers (yolcular) cars (arabalar) 3 . Bu rnekte yolcuo lar bir treni oluturan kompartmanlarda oturmaktadrlar. Her yolcu, passens gers tablosunda ismiyle kimliklendirilecektir, ve kompartmanlar compartment kolonu ile cars tablosu uzerinde tutulacaktr.
CREATE TABLE passengers ( name VARCHAR(15), compartment INT); INSERT INTO passengers VALUES (smith,20); INSERT INTO passengers VALUES (jones,25); CREATE TABLE cars ( compartment INT, class VARCHAR(10)); INSERT INTO cars VALUES (20,compartmant 1);

Bu emaya ve rnek veriye gre, smith adl yolcu 20 nolu ve cars tablosunda s o o mevcut bir kompartmanda oturmaktadr. Bizim sorguyla bulmak istediimiz g jones adl yolcudur, unk bu yolcu 25 nolu ve cars uzerinde olmayan bir c u kompartmanda oturmaktadr.
3 http://dev.mysql.com/tech-resources/articles/4.1/subqueries.html

288

ILISKISEL MODEL Not: Sadece rnek olarak verilmi bu emann gerek dnya artlarna o s s c u s pek uyduu sylenemez, unk bu tr bir uygulamalarda genelg o c u u likle carsn asal anahtar compartmant ve passengersdaki yabanc anahtar compartmant arasnda bir btnlk kontrol (9.1.1) uu u u konacak, ve passengersa yaplan her INSERT kontrol edilerek INSERT INTO passengers VALUES (jones,25) komutu bu kontrolden gemeyecekti. Sadece rnek amal olarak bu emay ve c o c s veriyi kullanyoruz, NOT EXISTS genellikle arasnda yabanc/asal anahtar ilikisi olmayan tablolar iin kullanlr. s c NOT EXISTS ieren alt sorgu kullanan rneimizdeki SQL komutu, yle c o g so olacaktr.
SELECT * FROM passengers WHERE NOT EXISTS (SELECT * FROM cars WHERE cars.compartment = passengers.compartment);

Bu sorguda ust sorgu, passengers tablosundaki verilerden sorgulamaya balamtr. s s Ust sorgudan sonra parantez iinde bir sorgu daha gryoruz, demek ki alt c ou sorgu mevcuttur. Alt sorgularn ileyiini hayal etmek iin yle dunmek s s c so us faydaldr; Sanki ust sorgudaki her satrn teker teker alt sorguya verildiini g dunn. Eer ust sorguda NOT EXISTS kullanm mevcut ise, ve alt alt sorguus u g dan, ust sorgudan verilen art kendi yapt baz ltrelemeler sonucunda hi g c bir sonu geri gelmez ise, ust sorgudaki NOT EXISTS artna uyulmu olaca c s s g iin, ustten alta verilmi olan satr, baarl bir satr olarak geri dndrlecektir. c s s o uu Alt sorguda cars.compartment kullanmna dikkat ekmek isterim; Yni c a ust sorgudaki tabloya alt sorgudan erimek mmkndr (ama tersi mmkn s u u u u u deildir). Ayrca bu durum nceki paragrafta bahsettiimiz ustten alta teker g o g teker gnderilen satrlar betimlemesine de uygundur. o Bu rnek sorgudan cevap olarak tek bir passengers satr geri gelecektir; o O da 25 nolu kompartmanda oturan jones adl kiidir. s

9.1.2

Veri Modelini Normlletirmek a s

Normlletirme (normalization), ilikisel bir veri taban modelinin daha ar hale a s s getirilmesidir. Normlletirme, ayn zamanda ilk taslak veri taban tasarmnn a s uzerinde revizyonlar yapmannn yolu, tasla son haline yaklatrmann yntem g s o lerden birisidir. Normlletirmenin altyaps matematikseldir, aynen ilikisel a s s modelin kendisinin matematiksel olmas gibi. Temel alnan kavram, ilevsel s ballk (functional dependency) denen bir kavramdr. Normalletirmenin amalar g s c unlardr. s Veri B t nl u: Sadece bu e bile normalletirme ile uramak iin u u ug og s g s c yeterli bir sebeptir. Veri, btnlu bozulmam bir ekilde kalr, unk her u u ug s s c u eit bilgi, sadece bir kere tek bir yerde saklanr. Yani, bir veri eidinin kopyasnn c s c s 289

9. VERI TABANLARI veri tabannn deiik izelgeleri uzerinde saklanmas gerekmez. Eer veri gerekgs c g siz ekilde kopyalanm ise, bu deiik kopyalar, kopyalardan habersiz olan s s gs uygulama kodlar yznden bir sre sonra birbirinden farkl deerleri tamaya u u u g s balayabilirler. Bu, doruluk ve tutarllk asndan ok kt bir sonutur. Bu s g c c ou c gibi durumlarda ilikisel veri taban paketinizin otomatik btnlk kontrol (aus uu u tomatic integrity check) mekanizmalar bile ie yaramaz. Tedavinin, uygulama s seviyesinde yaplmas gerekir. Fakat bu da uygulama programlarn daha kompleks hle getirecek, dolaysyla bakmn zorlatracaktr. a s Uygulamadan Bamsz Veri Modeli: Normalletirme, genelde bilinen g s ve takip edilen ilikisel model, verinin ieriine gre kurulmal, uygulamaya s c g o gre deil kavramn bir adm daha ne alr. Bu sayede veri modeli, uzerinde o g o onu kullanan uygulama deise bile daha tutarl, sabit ve deimez olarak kalags gs caktr. Uygulama programnn gereksinimlerinin veri taban mantksal (logical) model uzerindeki etkisi sfr olmaldr. Daha ileride greceimiz gibi, uygulama, o g mantksal model uzerinde deil, ziksel (physical) model uzerinde etki yapar. g Depolama Yeri Azaltm: Yabanc/gsterge anahtarlarn haricinde, tamamiyle o c normlletirilmi bir veri taban gereksiz (kopyalanm) veri miktarn en aza a s s s indirecektir. Kopyalanma miktar azald iin, depo yerine olan ihtiyata azalr. g c c Ve gene bu sayede, veri taban motorunun arama yapmas da daha rahatlaacaktr. s Birinci Normal Formu Bu form, tekrar eden hi bir gurup tamaz. Bir baka deyile, bir hcre uzerinde c s s s u tanan deer tek ve basit olmaldr. Aadaki rnek veride, son sene nfusu s g s g o u %5den fazla artm olan ehirlerden bazlarn gryoruz. Sehir bilgilerinin s s ou bazlarnn ayn hcre ierisinde guruplandn gryoruz. Bu yzden bu tablo, u c g ou u normal deildir (htta 1NF bile deildir). g a g Bu tablodaki bilgiye bakarak, ehir bilgilerinden mesela BU_YILIN_NFUSU s kolonundaki nfuslardan hangisinin hangi ehre ait olduunu nereden bilebilu s g iriz? Bir kolon iinde bile birok nfus ve birok ehir var. Sorumluluu veri c c u c s g modelinden uygulama programna atarak, sraya gre bir eleme dunlebilir, o s us u fakat bu da en temel ilikisel veri taban kural olan kolon iinde sra olmaz s c kuralnn ihlalidir. Bu veri yapsn 1NF (birinci normal formu) hline getirmek iin, tekrar a c eden guruplar (verileri) tek kolondan karp, deiik satrlara yaymak gerekir. c gs Alttaki tabloda 9.9 uzerinde, tablo 9.8 verisinin 1NFe getirilmi halini gre s o bilirsiniz. Bu yeni veri modelinde, eyalet kolonu asal anahtar (primary key) olarak addedildi. Fakat bu son tabloda da baz problemler var. Gncellemek ve silmek u iin, hala birok veriye teker teker urayp, verinin btnlun kod yazarak c c g u u ug u birarada tutmamz gerekiyor. Mesela eer yeni bir ehir satr ekleyecek olsak, g s beraberinde eyalet verisi de eklememiz lazm. Ya da bir eyaletin son ehrini s veri tabanndan silsek, bu eyaletin verisini veri tabanndan tamamen kaybetmi s oluyoruz. Demek ki 1NFten daha optimal bir yapya gememiz gerekiyor. c 290

ILISKISEL MODEL

Tablo 9.8: Normal Olmayan Tablo


EYALET KISALTMA EYALET NUFUSU SEHIR GECEN YILIN NUFUSU BU YIL NUFUS YUZDE ARTIS

North Carolina Vermont New York

NC

5M

Burlington, Raligh Burlington Albany, New York City, White Plains

40k, 200k 60k 500k, 14M,

44k, 222k 67.2k

10%, 11% 12%

VT NY

4M 17M

100k

570k, 14.7M, 106k

8%, 5%, 6%

Tablo 9.9: 1NF


EYALET KISALTMA EYALET NUFUSU SEHIR GECEN YIL NUFUS BU YIL NUFUS YUZDE ARTIS

North Coralina North Coralina Vermont New York New York New York

NC NC VT NY NY NY

5M 5M 4M 17M 17M 17M

Burlington Raleigh Burlington Albany New York City White Plains

40k 200k 60k 500k 14M 100k

44k 222k 67.2k 540k 14.7M 106k

10% 11% 12% 8% 5% 6%

291

9. VERI TABANLARI Ikinci Normal Formu 2NF yapsnda 1NF rneinde grdumz ekilde yarm bamllk bulunmaz. o g o ug u s g Anahtar olmayan her kolon, asal anahtara tamamen bal olmaldr. Anahtar g kolon, birden fazla kolonu kapsyorsa, anahtar olmayan kolonlar anahtar kolonlarn hepsine tamamen bal olmaldr. Tablo 9.9 bu kritere hla uymuyor. Sehir g a bilgileri eyalet bilgisine bal deil. Daha detayl olarak, btn ehir kolonlar g g uu s (SEHIR, GECEN_YIL_NUFUS, BU_YIL_NUFUS, YUZDE_ARTIS) asal anahtar eyalet kolonuna EYALET tamamen bal durumda deildir. g g Bu yzden, birbirine tam bal olmayan bilgileri ayr tablolara paralamamz u g c gerekiyor. Tablo 9.10 ve 9.11 uzerinde 2NF emann son hlini gryoruz. s a ou Tablo 9.10: 2NF Eyalet Tablosu
EYALET KISALTMA EYALET NUFUSU

North Carolina Vermont New York

NC VT NY

5M 4M 17M

Tablo 9.11: 2NF Sehir Tablosu


EYALET KISALTMA SEHIR GEC YIL NUFUS BU YIL NUFUS YUZDE ARTIS

North Coralina North Coralina Vermont New York New York New York

NC NC VT NY NY

Burlington 40k Raleigh 200k

44k 222k 67.2k 540k 14.7M

10% 11% 12% 8% 5%

Burlington 60k Albany 500k New York City White Plains 14M

NY

100k

106k

6%

c u Uunc Normal Formu 3NF veri modelinde, anahtar olmayan hibir kolon, baka anahtar olmayan c s kolona bal olamaz. 2NFde btn kolonlarn asal anahtara bal olduunu g uu g g 292

Yardmc Kavramlar sylemitik. 3NFe gre, bu balant dolayl bile olamaz. Mesela, YUZDE_ARo s o g TIS kolonuna bakalm. Bu kolon, GECEN_YILIN_NUFUSU ve BU_YILIN_NUFUSU kolonlarna baldr, unk bu iki kolondaki deerlerden hesaplanr (Hesag c u g planan kolonlara literatrde tretilen (derived) kolon ismi de verilmektedir). u u Uretilen kolonlar asal anahtara ballardr ama, bu ballk dolayldr, yani bal g g g olduklar esas iki kolon asal anahtara bal olduu iin onlar da asal anahtara g g c ballardr. g c u Uunc normal formunda byle kolonlara izin verilmez. YUZDE_ARTIS kolonu o 3NFde emadan atlmas gerekmektedir. Tretilen deerler, uygulama pros u g gram tarafndan anlk hesaplanacaktr. Eer hesaplanan deer ok sk eriiliyor g g c s ise, o zaman Oracle grnt kavram kullanlarak bu hesabn hayali bir tablo ou u erevesinde servis edilmesi performans asndan yararl olabilir. c c c Veri tabannn 3NF (en son) halini Tablo 9.12, 9.13 ve 9.14 uzerinde gryoruz. ou Tablo 9.12: 3NF
EYALET EYALET NUFUS

North Carolina Vermont New York

5M 4M 17M

Tablo 9.13: 3NF


EYALET KISALTMA

North Carolina Vermont New York

NC VT NY

9.2

Yardmc Kavramlar

Tablo, SQL gibi ana kavramlarn ustne, ou veri taban urn baz ek servis u c g u u leri kullanclarna sunmaktadr. Bu servisler, bir tablo uzerinde yaplan silme, gncelleme, ekleme gibi bir ilem olduu anda bir ek komutun iletilmesini u s g s salayan tetik (trigger) kavram olabilir. Tetik, norml proglamlama dillerinden g a bize tandk gelecek bir kavramdr, bir engel (hook) olarak grlebilir, ve c ou engel, takld yer aktif olunca kendisi de aktif hle gelecektir. Dier kavramc g a g lardan grnt (view), dizi (sequence) ve eanlam (synonym) saylabilir. ou u s 293

9. VERI TABANLARI Tablo 9.14: 3NF


SEHIR KISALTMA GECEN YIL NUFUS BU YIL NUFUS YUZDE ARTIS

Burlington Raleigh Burlington Albany New York City White Plains

NC NC VT NY NY

40k 200k 60k 500k 14M

44k 222k 67.2k 540k 14.7M

10% 11% 12% 8% 5%

NY

100k

106k

6%

Bu kavramlar imdiye kadar Oracle uzerinde kullandmz iin, bu blmde s g c ou de Oracle uzerinden ileyeceiz. Fakat kendi urnnz uzerinde bu kavramlarn s g u u u karlklarn bulabilirsiniz (zellikle PostgreSQL uzerinde, unk bu taban zels o c u o lik olarak Oraclea en yakn olan ak yazlm urndr). c u u u SID Veri taban kelimesini kullandmzda genelde birok eyden ayn anda bahsediyg c s oruz. Oracle paket programnn tamamna, iinde bilgi depolayan kaytlar, c kullanc isimlerinin toplamina ayn anda veri taban deniyor. Fakat, Oracle dunyasinda, bu kavramlari daha da berraklatrmamz gerekecek. SID= Veri s taban diyeceiz, ve, veri taban Oracle paket program deildir gibi bir tanm g g yapacaz. Peki o zaman, veri taban nedir? g Oraclea gre veri taban, hakknda konuabileceimiz en byk kayt biro s g u u c imidir. Iinde tablolar, onlarn yazld dosyalar, bu tablolara eriecek kullanc g s isimleri, ve paralolarn toplamna veri taban diyoruz. Bir proje icinde u kes limeleri duyabilirsiniz. Hangi veri tabanna balandn, tablo xi bu tabanda bulamyorum... g (Admine) Benim kullanc ismimi bu veri tabannda da yaratr msnz ? Kullanc ifrem kabul edilmiyor s Fazla veri taban yaratmaya gerek yok, bir tane uzerinde alsak olmaz c s m? Hayr olmaz, unk veri taban idarecileri iki veri taban olursa idaresi c u kolaylar diyorlar. s SID, veri tabanna erimemizi saylayacak bir isimden ibarettir. Ornek olarak s SATIS, BORDRO, MUSTERI gibi veri taban isimleri olabilir. 294

Yardmc Kavramlar

9.2.1

Tablo Alan

Tablo alan (tablespace), tablolarn uzerinde depolanaca dosya ismidir, yni g a /usr/dizin1/dizin2/cizelge_alan_1.dbf gibi bir gerek Unix dosyasndan c bahsediyoruz. Oracle veri tabannn, gerek dnya ile (iletim sistemi) bulutuu c u s s g yere tablo alandr.Tablo ile tablo alanlarnn balants, alan yaratlrken sdece g a bir kere yaplr. Ondan sonra ne zaman bu tabloya eriseniz, nceden tanmlanm s o s olan dosyadan oku/yaz otomatik olarak yaplacaktr. Tablo alan yaratmak iin, yle bir komut iletebiliriz. c so s
CREATE TABLESPACE cizelge_alan_1 DATAFILE /usr/local/dizin1/oracle/cizelge_alan_1.dbf SIZE 200M;

9.2.2

Sema

Sema=kullanc gibi bir tanm yapabiliriz, fakat Oracle dnyasnda ema biraz u s daha gl bir kavramdr. Eer daha basit veri tabanlarna alksak, herhalde uc u g s her kullancnn her tabloyu grmesine alzdr. Fakat Oracle iin tablolarn o sg c eriilip eriilmeyecei, tablolarn nerede tutulaca (yni sahiplenme mekanizs s g g a mas) ema baznda idare edilmektedir. Bir veri tabanna (SID=ORNEK1) balandnz s g g zaman, bu tabanda baz tablolar gremeyebilirsiniz. Grmek iin, belli bir kulo o c lanc ve ema kullanarak balanmanz gerekecektir. Ayn isimdeki iki tabloyu s g deiik emalarda yaratabiliriz; Oracle bundan yaknmaz. Yni SIDden sonra gs s a Oracle paylatrmann/blmenin ikinci bir yolu emadr. s o s Oracle idarecileri az miktarda SID ve paylatrmak iin ok miktarda ema s c c s yaratmay tercih ederler. Sema yaratmak iin kullanc yaratmamz yeterlidir. c
CREATE USER hasan IDENTIFIED BY hasanslx DEFAULT TABLESPACE alan1;

Bu konu hakknda baz notlar unlardr: s Kullanc MEHMET olarak SIDe balandysanz, ve CREATE TABLE g komutunu iletip bir tablo yarattysanz, bu tablo MEHMET emasna ait s s olacaktr. Bu tabloyu bakalar gremez. Grmesi iin zel izin vermeniz s o o c o gerekir. Eer MEHMET kullancs olarak bir tablo yarattysanz ve detay beg lirtmediyseniz, bu tablo DEFAULT TABLESPACE diye yukarda belirttiimiz yokluk deeri (default) alan1 altnda yaratlr. g g

9.2.3

Gr nt o u u

Grntler, nceden depolanm ve sorgulanabilen SQL kodlardr. Bir grnt, ou u o s ou u gvenlik tr baz izgeleri gstermeden, bu izgelerin verisinin bir ksmn u ouu c o c gstermek iin kullanlabilir. Mesela halkla ilikiler blm iin, isim, soyad ve o c s ou u c adres bir grnt iinden gsterilebilir, teki bilgiler saklanabilir. Ya da, dank ou u c o o g 295

9. VERI TABANLARI veri tabanlarndan toparlanacak bilgiler, bir grnt ile nceden kodlanr ise, ou u o artk birden fazla veri tabanna balanmak yerine, tek bir grnt uzerinden g ou u veri alnabilir. Ozet olarak, normalde ileyen her SQL kodu, grnt yaramak s ou u iin kullanlabilir. c
create or replace view goruntu_1 as select isim, soyad from MUSTERI;

9.2.4

Dizi (Sequence)

Tekil say yaratmak iin kullanlan Oracle nesnesine dizi ad verilir. Dizi yaratc mak iin balang deeri, art miktar ve biti says vermek yeterlidir. Yani, c s c g s s 1..n aras her seferinde 1 kadar artacak bir dizi yaratmak mmkn. Bu saylar u u genelde kimlik no gibi zgn olmas gereken deerler iin kullanlr. Her seo u g c ferinde kod iinde, nceki deer + 1 demek yerine, SQL kullanarak her diziden c o g yeni say isteyiimizde, gncel dizi art deeri kadar otomatik olarak arttrlr s u s g ve alnan say SQL sonucu olarak verilir. Bir dizi yarattnz zaman, NEXTVAL ve CURRVAL sanal kolonlarn kullanrz. g Mesela UYE_DIZISI adl bir dizi yaratt isek, SELECT UYE_DIZI.NEXTVAL FROM DUAL diyerek o anki deeri alabiliriz. Bu komut sonucunda ayrca dizi deeri g g 1 arttrlr. SELECT UYE_DIZI.CURRVAL FROM DUAL kullanm o anki deeri g verecektir. Fakat diziyi arttrmaz.
CREATE SEQUENCE DIZI_ISMI INCREMENT BY 1 -- art s START WITH 100; -- balang s c

9.2.5

Tetik

Tetikler (trigger), depolanm PL/SQL kodlardr. Onceden ngrlen belli s o ou baz tablolara, gene nceden ngrlen ekilde bir eriim olduunda tetikler o o ou s s g atelenirler, ve kodlanan ilemi yerine getirirler. Tetikler, satr ekleme, silme, s s gncelleme ya da btn bu temel ilemlerin deiik guruplamalar iin kodlanu uu s gs c abilirler. Tetiklerin en ok kullanld alan, veri btnlu iin kstlamalar c g u u ug c koymaktr. Bu tr kstlamalar Oracle terimleri ile, veri btnlk kontrolleri u uu u (integrity constraints) olarak bilinir, ve satrlar arasnda baz kontroller getirebilir. Fakat bu tr satr bazl kontrollerin yetmedii hallerde, tetik kodu g lar ie yarayabilir. Cunk tetik kodlar iine PL/SQL ile kodlayabildiiniz her s u c g trl kod koyabilirsiniz. u u
create to replace trigger musteri_tetik_1 INSTEAD OF insert on musteri for each row begin insert into maas values (1, 2); -- buraya daha deiken kod koyabilirsiniz g s

296

Yardmc Kavramlar
end; /

9.2.6

Dizi ve Tetik

Baz veri emalarnda ID kolonu atanan bir deer deil, uretilmesi gereken bir s g g saydr. Bu say, en basit hliyle 1den balayarak her yeni veri satr iin birer a s c farkla artmas gereken bir saydr. O zaman her satr yazarken bu IDnin uretilmesi gerekmektedir. Bu ure timi, ya uygulama iinde yapacaz, ya da veri tabann otomatik olarak yapc g masn salayacaz. g g Otomatik attrm baz veri tabanlarnda bir kolon tipi olarak bile karnza s kabilir. Oracleda bu ii yapmak iin bir sequence ve bir trigger kullanmamz c s c gerekiyor. Oracle, bu tekil saynn uretimini ve tabloya atanmas iini bir s birinden ayrmtr. Bu da sanyorum isabet olmutur, auto-increment kolon s s tipi hakikaten ok basitleyici bir zmdr. c co u u Oracleda otomatik ID uretimi iin iki ey gerekir; Bir sequence, bir de c s trigger. Mesel, yle bir tablomuz olduunu dunelim. a so g us
create table test ( id number, veri varchar2(20), ... );

Bu tablo iin bir sequence ve bir trigger yaratalm. c


create sequence test_seq start with 1 increment by 1 nomaxvalue ; create trigger test_trigger before insert on test for each row begin select test_seq.nextval into :new.id from dual; end; INSERT into test (veri) values (blablabla);

gibi bir INSERT kullandmzda, hi IDye dokunmamza gerek kalmadan, bir g c sonraki ID says hesaplanacak ve kolona koyulacaktr. 297

9. VERI TABANLARI

9.2.7

Veri Taban Kpr s o u u

Kprler (database link) nesne (tablo, kolon, vs) baznda deil, tm veri taban o u g u baznda balant kurar. Yani, uzakta olan bir veri tabanna, srekli olarak g u ve uzak adresini kullanarak erimek istemiyorsanz, bir kpr, yani kestirme s o u yaratarak o veri tabanna sanki yerel bir tabanm gibi eriebilirsiniz. s s
CREATE PUBLIC DATABASE LINK baglanti_1 CONNECT TO kullanici IDENTIFIED BY sifre USING UZAK_VERI_TABAN_SID_DEGERI;

9.2.8

Eanlam (Synonym) s

Eanlamlar, bir veri tabanndaki tablolarden dier tablolara kestirme iaret s g s olarak grlebilir. Bir eanlam yaratmak iin eanlam ismi, ve o eanlamn ou s c s s yerini tuttuu Oracle nesnesinin ismi gereklidir. SQLPlus kullanarak bu eanlama g s eritiimizde, Oracle arka planda eanlamn yerini tuttuu nesneyi bulur, ve s g s g ilemi o teki nesne uzerinde yapar. s o Iki trl eanlam vardr. Umumi (public) ve zel (private). Ozel eanlamlar u u s o s iinde yaratldklar emaya zel olurlar, o emaya ait kalrlar ve baka kulc s o s s lanclar tarafndan eriilemez, hatta grlmezler bile. Eer eanlamlar umumi s ou g s ise, btn ematikler tarafndan kullanlabilirler. uu s Oraclen bir nesneye erimek iin hangi tr bir algoritma izlediine gelelim. s c u g Eer yle bir kod iletildi ise, g so s
SELECT * FROM FROM MAAS

Oracle MAAS nesnesini bulmak iin unlar yapar. c s MAAS adl bir tablo ya da grnt var m? ou u Bu ikisi yoksa, Oracle MAAS adnda zel bir eanlam arar. o s Var ise, zel eanlamn gsterdii nesne kullanlr. o s o g Yok ise, MAAS adl umumi eanlam aranr. s Hibiri yok ise, Oracle ORA-00942 hata mesajn verecektir. c
create synonym MUSTERI for BIZIM_UZUN_MUSTERI_ISMI;

298

Yardmc Kavramlar

9.2.9

Indeksler

Bir tablodan veri almak iin, kullandmz SELECT komutunun WHERE ksm c g iinde ltre artlar belirtmemiz gerekir. Bu artlar, veri taban tablosu taranrken c s s gereken satrlar dierlerinden ayrp onlar ekip karabilmemiz iin kullanlr. g c c c Arama artlar tanmlandktan sonra, veri taban kapal perdeler arkasnda s tarama ilemini gerekletirmek iin unlar yapar: Tabloyu tararken, ilk satrdan s c s c s balayp teker teker sonuncu satra doru tm satrlara bakar, ve ltre artlarnn s g u s uyup uymadn kontrol eder. g Fakat tm satrlara baklan trden bir arama, zellikle byk tablolar u u o u u iin ok uzun zaman alacaktr. Eer tm satrlara baklan trden bir tarama c c g u u yaplmasn istemiyorsak, veri tabanna arama yaparken bir ekilde yardm ets menin yolunu bulmalyz. Indeksler bu trden yardm yntemidirler. Indeksler, kendileri veri iermezler, u o c sadece gerek veriyi ieren tablonun belli satrlarna iaretler tarlar. Cok hzl c c s s aranabilen trden veri yaplardrlar. Bu iaretler, belli anahtar kolonlarna gre u s o (indeksle) yaplmtr. Indeksler bu adan bir hriste benzerler. s c Bir indeksin kullanma konmas yle olur: Eer SELECT ltremiz iinde so g c kullanlan kolonlar uzerinde bir indeks mevcutsa, veri taban ltreyi nce in o deksden tarar, buradan gelen satr iaretini kullanarak ta gerek tabloya giderek s c aranan gerek satr dndrr. c o uu Indeksler gerek tabloyu indeksledikleri iin, bu tabloda olan her deiim c c gs indeksleri etkiler. Mesel tabloya yeni bir satr eklenirse, indeks bu ekleme a ilemini yanstacak ekilde gncellenir. Bu sebeple gereinden fazla indeks eks s u g lenmesi bir tabloya yaplan INSERT ilemlerini yavalatacaktr. Tam kararnda s s kurulan indeksler, hem SELECT sorgularmz hzlandrr, hem de INSERTlerimiz uzerinde fazla bir etkide bulunmazlar. Su anda piyasada olan her profosyonel veri taban urn, indeks teknolojisini u u desteklemektedir. Bu blmn geri kalannda PostgreSQL, Oracle ve MySQL ou u tabanlarnda indeks eklemenin yollarn, ve en nemlisi, herhangi bir sorgunun o uzerinde analiz yaparak indeks kullanp kullanmadn grebilmek iin gereken g o c komutlar greneceiz. o g Elimizde car ve garage adl iki tablo olduunu dunn. Bu tablolar arasnda g us u bire ok trnden bir iliki olsun ve bir car birok garajn altnda olabilsin. Bu c uu s c ilikiyi ziksel anlamda, car tablosu uzerinde bir garage_id koyarak gerekletiriyoruz. s c s PostgreSQL Bir sorgunun indeks kullanp kullanmadn analiz etmek iin, o sorguyu psql g c ile PostgreSQL komut satrna girip, EXPLAIN komutu eliinde iletmemiz s g s gerekmektedir.
explain select * from car where license_plate = 34 THY 334;

Eer hibir indeks tanmlamamsak, yle bir cevap geriye gelecektir. g c s so 299

9. VERI TABANLARI
QUERY PLAN -------------------------------------------------------Seq Scan on car (cost=0.00..330.00 rows=44 width=170) Filter: ((license_plate)::text = 34 THY 334::text)

Bu ktda ilk dikkatimizi eken kelimeler, Seq Scan kelimeleri olmaldr. Bu c c kelimeler Sequential Scan (srayla tarama, teker teker bakma) kelimesinin bir ksaltmasdr, ve SELECT komutunun teker teker her satra bakt anlamna g gelir. Bu performans asndan istediimiz bir durum deildir. Biz indekslerin c g g kullanlmasn istiyoruz. Ve grdk ki, hibir indeks kullanlmamstr. Cunk daha o u c u indeks tanmlamadk! Ayn ekilde, s
explain select c.* from car c, garage g where c.garage_id = g.id and g.id = 2 and c.available = t;

sorgusunun analizi de u cevab getirecektir. s


QUERY PLAN ---------------------------------------------------------------------Nested Loop (cost=18.50..372.26 rows=88 width=170) -> Seq Scan on car c (cost=0.00..352.00 rows=22 width=170) Filter: ((available = true) AND (2::numeric = garage_id)) -> Materialize (cost=18.50..18.54 rows=4 width=23) -> Seq Scan on garage g (cost=0.00..18.50 rows=4 width=23) Filter: (id = 2::numeric)

Cok kt. Bu sorguda da, hem iki tablo birletirimi (join) hem de available ou s kolonu uzerinde yaptmz ltreleme uzerinde seq scan taramas yapldn g g gryoruz. Satr says olduka fazla olan car ve garage tablolar kullanyor ou c olsaydk, bu son sorgunun da performan ok kt olacaktr. c ou O zaman indeksleri ekleyelim. PostgreSQLda indeks yle eklenir: so
CREATE CREATE CREATE CREATE UNIQUE INDEX car_license_plate_idx on car (license_plate); UNIQUE INDEX garage_id_idx on garage (id); INDEX car_available_idx on car (available); INDEX car_garage_idx on car (garage_id);

car tablosunda license_plate kolonu uzerinden ileyen bir indeks ekledik. s Ayn ekilde garage.id kolonuna, car.available kolonuna ve car.garage s _id kolonuna indeksler ekledik. Indeksler eklendikten sonra, srasyla her iki sorguda yaplan EXPLAIN komutu, u sonucu dndrecektir. s o u
QUERY PLAN --------------------------------------------------------------------------

300

Yardmc Kavramlar
Index Scan using car_license_plate_idx on car (cost=0.00..6.00 rows=1 width=170) Index Cond: ((license_plate)::text = 701790-171::text) QUERY PLAN --------------------------------------------------------------------------Nested Loop (cost=0.00..15.03 rows=2 width=170) -> Seq Scan on garage g (cost=0.00..1.05 rows=1 width=23) Filter: (id = 2::numeric) -> Index Scan using car_garage_idx on car c (cost=0.00..13.96 rows=2 width=170) Index Cond: (2::numeric = garage_id) Filter: (available = true)

Sonuca bakarak gryoruz ki, birinci sorguda Seq Scan ibaresinde kurtulduk. ou Artk bu sorguya eriim, Index Scan ile olmaktadr, yni verdiimiz sorgu s a g car tablosuna yarattmz indeks uzerinden eriilmektedir. Bir hz ilerlemesi g s kaydettik. Ikinci sorguda, available kolonu uzerindeki sorgudaki ltre ibaresi de indeks kullanmaya balamtr. s s Fakat PostgreSQL sorgu hzlandrcs (optimizer), garage.id uzerindeki indeksi devreye sokmamtr, unk garage tablosunda ok az veri vardr (rnek s c u c o verimiz byle idi) ve bu ekilde az veri tayan tablolarda indeks kullanp kulo s s lanmamak bir hz fark getirmeyecektir. Oracle Oracle uzerinde indeks yaratmak iin CREATE INDEX, sorgularn indeks kul c lanmn analiz etmek iin EXPLAIN PLAN komutlar kullanlr. EXPLAIN PLAN, c komutu ilettiini emada ileyebilmek iin PLAN_TABLE adl bir sistem tablos g s s c sunu kullanr. Oracle 10g uzerinde bu tablo her veri taban iinde kurulmu c s olur, ama eer kullandnz versiyonda mevcut deilse, tabloyu u komut ile g g g s yaratabilirsiniz (ORACLE_HOME, Oracle paketinin kurulmu olduu dizini temsil s g eder).
\$ sqlplus user/pass@SID @ORACLE_HOME/product/<versiyon>/<Db>/rdbms/admin/utlxplan.sql

utlxplan.sql dosyasnda plan_table ve ilgili tm tablolarn yaratlmas iin u c gereken ilemler yaplmaktadr. s Analiz iin u komutu kullanabilirsiniz. c s
explain plan SET STATEMENT_ID=SORGU_1 FOR select * from car where license_plate = 34 THY 334; SELECT LPAD( ,2*DEPTH) | | OPERATION | | | | OPTIONS | | | | OBJECT_NAME | | | | DECODE(ID, 0, COST= | | POSITION) "QUERY PLAN" FROM PLAN_TABLE START WITH ID=0 AND STATEMENT_ID=SORGU_1

301

9. VERI TABANLARI
CONNECT BY PRIOR ID=PARENT_ID;

Sonu yle gelir: c so


QUERY PLAN --------------------------------SELECT STATEMENT COST= 3 TABLE ACCESS FULL CAR

Bu iletim planna bakarsak, TABLE ACCESS FULL kelimelerini hemen gzmze s o u u arpar. Bu kelimeler bize iletilen sorgunun hibir indeks kullanmadn gsterc s c g o mektedir, ve Oracle tablodaki satrlara teker teker ve srayla erimeye almaktadr. s c s Ayn ekilde dier sorgumuza bakarsak; s g
explain plan SET STATEMENT_ID=SORGU_1 FOR select c.* from car c, garage g where c.garage_id = g.id and g.id = 2 and c.available = t; SELECT LPAD( ,2*DEPTH) | | OPERATION | | | | OPTIONS | | | | OBJECT_NAME | | | | DECODE(ID, 0, COST= | | POSITION) "QUERY PLAN" FROM PLAN_TABLE START WITH ID=0 AND STATEMENT_ID=SORGU_1 CONNECT BY PRIOR ID=PARENT_ID;

u sonucu grrz s ouu


QUERY PLAN ---------------------------------SELECT STATEMENT COST= 6 MERGE JOIN CARTESIAN TABLE ACCESS FULL CAR BUFFER SORT TABLE ACCESS FULL GARAGE

Bu analiz sonucunda da bol bol TABLE ACCESS FULL grmekteyiz. Demek ki o gerekli yerlere indeksler eklememiz gerekiyor.
CREATE CREATE CREATE CREATE UNIQUE INDEX car_license_plate_idx on car (license_plate); UNIQUE INDEX garage_id_idx on garage (id); INDEX car_available_idx on car (available); INDEX car_garage_idx on car (garage_id);

Simdi EXPLAIN PLANi tekrar iletirsek, u sonular greceiz. s s c o g 302

Yardmc Kavramlar
QUERY PLAN ----------------------------------------------SELECT STATEMENT COST= 1 TABLE ACCESS BY INDEX ROWID CAR INDEX UNIQUE SCAN CAR_LICENSE_PLATE_IDX QUERY PLAN ------------------------------------------------SELECT STATEMENT COST= 0 NESTED LOOPS INDEX UNIQUE SCAN GARAGE_ID_IDX TABLE ACCESS BY INDEX ROWID CAR BITMAP CONVERSION TO ROWIDS BITMAP AND BITMAP CONVERSION FROM ROWIDS INDEX RANGE SCAN CAR_AVAILABLE_IDX BITMAP CONVERSION FROM ROWIDS INDEX RANGE SCAN CAR_GARAGE_IDX

Bu sonular ok daha iyidir. Birinci sorgunun analizi TABLE INDEX BY ROWID c c CAR kelimesini tayor, bu demektir ki tabloya eriim artk bir indeks uzerinden s s gereklemektedir. Kullanlan indeks CAR_LICENSE_PLATE_IDX isimli indekstir, c s bu da hemen altndaki satrda belirtilmitir. s Ikinci sorgunun sonucu biraz daha etreldir, fakat burada da grldu gibi c o u ug artk TABLE ACCESS FULL sz kaybolmutur, onun yerine indekslerin kulo u s lanlmaya baland INDEX UNIQUE SCAN, INDEX RANGE SCAN ve TABLE ACs g CESS BY ROWID kelimelerinden belli olmaktadr. INDEX UNIQUE ile INDEX RANGE arasndaki fark, ilkinin tekil bir satra iaret edebilmesi, ikincisinin tekrar eden s anahtar deerlere iaret eden trden bir indeks olmasdr. g s u Sonu olarak Oracle dnyasnda sorgu optimizasyonu ile amacmz, EXPLAIN c u PLANden gelen sonularda grlebilecek TABLE ACCESS FULL ibaresinden kurc ou tulmaktr. MySQL MySQL veri tabannda analiz iin explain komutu kullanlr. Aynen Postc greSQL rneinde olduu gibi, analiz etmek istediiniz sorgunun nne exo g g g o u plain ibaresini eklerseniz, MySQL analiz sonucunu gsterecektir. Ornek olarak o car ve garage uzerindeki yaplan iki sorguyu analiz edelim:
explain select * from car where license_plate = 32 TF 22;
+-------+------+---------------+------+---------+------+------+-------------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------+------+---------------+------+---------+------+------+-------------+ | car | ALL | NULL | NULL | NULL | NULL | 5 | Using where | +-------+------+---------------+------+---------+------+------+-------------+

303

9. VERI TABANLARI
explain select c.* from car c, garage g where c.garage_id = g.id and g.id = 2 and c.available = t;
+-------+------+---------------+------+---------+------+------+-------------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------+------+---------------+------+---------+------+------+-------------+ | c | ALL | NULL | NULL | NULL | NULL | 47 | Using where | | g | ALL | NULL | NULL | NULL | NULL | 4 | Using where | +-------+------+---------------+------+---------+------+------+-------------+

explain komutundan gelen ustteki sonular, her tablo iin bir satr olmak c c uzere listelenecektir. Her tabloya yaplan eriimin yntemini, type altnda bu s o labilirsiniz. MySQL dnyasnda, sorgu analizinde bir tablo iin type iin ALL u c c grmek iyi deildir. type iin gelmesi muhtemel deerleri en iyiden en ktye o g c g ou olacak ekilde bir sralamasn aada gryoruz. s s g ou 1. system 2. const 3. eq_ref 4. ref 5. ref_or_null 6. index_merge 7. ununique_subquery 8. range 9. index 10. ALL ALL deeri en alttadr, yni yukardaki sorgularmzn eritii tablolara indeks g a s g eklemezsek, yukardaki sorgular en kt performans ile iletiliyor olacaktrlar. ou s O zaman bu durumu dzeltmek iin indekslerimizi ekleyelim: u c
CREATE UNIQUE INDEX garage_id_idx on garage (id); CREATE INDEX car_available_idx on car (available); CREATE INDEX car_garage_idx on car (garage_id); CREATE UNIQUE INDEX car_license_plate_idx on car (license_plate); alter table garage add PRIMARY KEY(id); alter table car add PRIMARY KEY(license_plate); alter table car add FOREIGN KEY (garage_id) REFERENCES garage(id);

304

Yardmc Kavramlar Tekrar explain eliinde iki sorguyu iletelim ve sonular grelim. s g s c o
+-------+-------+-----------------------+---------+---------+-------+------+-------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------+-------+-----------------------+---------+---------+-------+------+-------+ | car | const | PRIMARY,license_plate | PRIMARY | 30 | const | 1 | | +-------+-------+-----------------------+---------+---------+-------+------+-------+ +-------+-------+---------------+-----------+---------+-------+------+-------------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------+-------+---------------+-----------+---------+-------+------+-------------+ | g | const | PRIMARY,id | PRIMARY | 31 | const | 1 | | | c | ref | garage_id | garage_id | 32 | const | 10 | Using where | +-------+-------+---------------+-----------+---------+-------+------+-------------+

Sonular daha iyileti. Birinci sorguda car tablosuna olan eriim, sorgu c s s iyilik derecesinde 2. seviyede olan const seviyesine ykseldi. Ikinci sorguda ise u garage (g) ve car (c) tablolarnn eriimi ise garage iin const ve car iin s c c iyilik derecesinde 4. seviyede olan ref eriimine ykseldi. s u

9.2.10

Oracle SQL*Loader

Metin bazl bilgileri Oracle veri tabanna yklemek istiyorsanz, bunun en rau hat yolu SQL*Loader adl program kullanmaktr. SQL*Loader, kontrol dosyas denilen bir ayartanm dosyas eliinde, virgl ayrml, boluk ayrml, tab s g u s ayrml, ya da sabit uzunluktaki kolonlar ieren metinlerin hepsini veri tac banna ykleyebilir. Bunu bir rnek uzerinde grelim: Once uzerinde ykleme u o o u yapacamz tabloyu veri tabannda yaratalm. g
create table musteri ( cust_nbr cust_name cust_addr1 cust_addr2 cust_city cust_state cust_zip cust_phone cust_birthday / create table hesap ( cust_nbr acct_nbr acct_name / number(7) number(10) varchar2(40) not null, not null, not null) number(7) varchar2(100) varchar2(50), varchar2(50), varchar2(30), varchar2(2), varchar2(10), varchar2(20), date) not null, not null,

Ustteki komutlar kullanarak tabloyu yarattktan sonra, rnek metin dosyalarn o SqlLodader projesinden alp kullanabilirsiniz. 305

9. VERI TABANLARI Sabit Uzunluklu Kayt Y klemek u Simdi, SQL*loadern almas iin bir kontrol dosyas lazm. Mteri verisi iin c s c us c yazlms aadaki kontrol dosyas rneini, load1.ctl adnda diskinize yazn. Bu s g o g rnek, sabit uzunluklu bir veri dosyasn yklemek iin verilmitir. o u c s
LOAD DATA INFILE cust.dat INTO TABLE musteri (cust_nbr POSITION(01:07) INTEGER EXTERNAL, cust_name POSITION(08:27) CHAR, cust_addr1 POSITION(28:47) CHAR, cust_city POSITION(48:67) CHAR, cust_state POSITION(68:69) CHAR, cust_zip POSITION(70:79) CHAR, cust_phone POSITION(80:91) CHAR, cust_birthday POSITION(100:108) DATE "DD-MON-YY" NULLIF cust_birthday=BLANKS)

Artk mteriyi veri tabanna yklemeye hazrz. Aadaki komut ile bunu us u s g yapabiliriz.
\$ sqlldr kullanici/sifre control=load1.ctl log=load1.log bad=load1.bad discard=load1.dis

Bilgisayardan gelen yant:


SQL*Loader: Release 8.0.3.0.0 - Production on Wed Mar 10 8:10:23 1999 (c) Copyright 1997 Oracle Corporation. All rights reserved. Commit point reached - logical record count 23

Cktya (sqlloader_musteri_cikti.txt) bakarak SQL*Loadern baarya ulap s s ulamadn anlayabiliriz. s g Bu sonuca gre, olanlar unlardr: 2inci kayt veri tabanna kabul edilmedi, o s unk tarih verisi Oracle tarafndan geersiz bulundu. Bu geersiz kayt, kt (bad) c u c c ou dosyasna yazld. Kt dosyasnn ismini komut satrndan bad=load1.bad ou ibaresini kullanarak verilmiti. s Deiken Uzunluklu Kayt Y klemek gs u Simdi hesap verisini virgl ayrkl bir veri dosyasndan veri tabanna ykleyelim. u u Bu ekilde bir ykleme iin lazm olan kontrol dosyas (load2.ctl) aadadr. s u c s g
LOAD DATA INFILE acct.dat INTO TABLE hesap FIELDS TERMINATED BY , OPTIONALLY ENCLOSED BY " (cust_nbr, acct_nbr, acct_name)

306

Yardmc Kavramlar Bu kontrol dosyasn da komut satrndan iletelim. s


\$ sqlldr kullanici/sifre control=load2.ctl log=load2.log bad=load2.bad discard=load2.dis

Bilgisayardan gelen yant:


SQL*Loader: Release 8.0.3.0.0 - Production on Wed Mar 10 8:10:23 1999 (c) Copyright 1997 Oracle Corporation. All rights reserved. Commit point reached - logical record count 12

Cktya (sqlloader_hesap_cikti.txt) bakarak SQL*Loadern baarya ulap s s ulamadn anlayabiliriz. s g Bu ktya bakarak, u sonuca varabiliriz: Btn kaytlar hatasz bir ekilde c s uu s yklendi. Bu rnek veri dosyas deiken uzunluklu veri ierdii iin, metin u o gs c g c dosyasnn iinde bir ayra gerektiini hatrlatmamz lazm. Bu rnek iinde c c g o c ayra olarak virgl iareti kullanldk. c u s Kayt Eklemek INTO TABLE hesap eklindeki szdizimi, bo olan bir tablo farzediyordu. Eer s o s g iinde zaten veri mevcut olan bir tabloya veri eklemek istiyorsanz, INTO TAc BLE ifadesinin bana APPEND eklemeniz gerekiyor. Yani, s
LOAD DATA INFILE acct.dat APPEND INTO TABLE hesap FIELDS TERMINATED BY , OPTIONALLY ENCLOSED BY " (cust_nbr, acct_nbr, acct_name)

Ozet SQL*Loader iin gereken ayarlar burada zetleyelim. c o Yklenecek veri dosyasnn ismi, kontrol dosyasnda INFILE ibaresinden u sonra verilir. Hedef tablosunun ismi, kontrol dosyasnda INTO TABLE ibaresinden sonra gelir. Deiken uzunluklu veri dosyalar iin ayra karakteri, kontrol dosyasnda gs c c FIELDS TERMINATED BY ibaresinden sonra verilir. Sabit uzunluklu veri dosyalar iin balang ve biti kolonlar, kontrol c s c s dosyasnda POSITION(BASLANGIC:BITIS) olarak tanmlanr. 307

9. VERI TABANLARI

9.3

Transaction

Veri tabann uzerinde iletilen her SQL komutu bir transaction altnda yaplr. s Transaction, bir ve ya daha fazla SQL ilemini kapsayabilir, zten ounlukla s a c g kullanlma amac budur: Hep beraber etki etmesi gereken deiiklikler iin gs c birletirici bir unite salamak. 2.2.5 blmndeki rnei tekrarlamak gerekirse, s g ou u o g bir banka uygulamasnda bir mterinin iki banka hesab olsa, ve bu mteri bir us us hesaptan tekine para transfer etmek istese, transaction sayesinde bir hesaptan o eksiltmek iin yaplan UPDATE SQL ilemi, para eklemek iin yaplan ekleme UPc s c DATE SQL ilemi ile ayn anda etki edebilecektir. Bu iki ilemi ayn transaction s s altna koyabiliriz. Transaction kavram, bir ilikisel tabanda veri doruluunu, veri taban s g g balantsn, tablolar uzerine konan kilitleri ve verinin en son grntsn big ou uu u raraya getiren ve hepsi ile yakn alkas olan merkezi bir kavramdr. Bir taa banda gerekletirdiimiz her SQL sorgusu, bu sebeple, bir transaction altnda c s g yaplacaktr; Eer bundan haberimiz yoksa, yni bilerek bir transaction balatp g a s durdurmuyorsak kapal kaplar altnda bizim iin bir tane muhakkak balatp c s bitiriliyordur. SQL kullanrken bir transactionn balamas, SQL sorgusunun tabana gelmes siyle ya da transaction balatma emrinin verilmesiyle olur. Eer o anda ileyen s g s baka bir transaction yok ise, taban bir tane otomatik olarak balatr. Transacs s tionn bitmesi commit ya da rollback komutlarndan bir tanesi ile olacaktr. Commit, o transaction altnda yaplan deiikliklerin kalc olmasna karar vergs ildii anlamna gelir. g Bir commit gelmeden nce dier transactionlar (yni dier veri taban balantlarnda o g a g g SQL iletmekte olanlar) bizim son deiikliklerimizden tamamen habersiz olas gs caklardr. Bu dier balantlar, sadece verinin bizim transaction balad ang g s g daki son hlini grrler. Ama bizim balantmz iinde iinde biz kendi gncelleme, a ou g c c u silme, ekleme ilemlerimizin sonucunu grebiliriz. s o Eer bir transaction altndayken (ve bir takm ilemlerden sonra) bir rollg s back komutu gelirse, bu, yaplan veri deitirme ilemlerinden vazgeildii angs s c g lamna gelecektir. O zaman veri taban, yaplan hibir deiiklii kalc yapmaz, c gs g ve teki balantlar ve transactionlar eski veriyi grmeye devam ederler. o g o Not: Gnmzdeki popler kullanma gre iki deiik transaction, u u u u o gs her zaman iki deiik balant (db connection) anlamna gelir. Ayn gs g balant iinden iie gemi (nested) transaction balatmak gerekg c cc c s s siz bir karmaklk yaratmaktadr, ve bu sebeple konumuz dndadr. s s Eer bir transaction balatm sre (process) kerse, o veri taban balants, g s s u c co g ve o balantda balatlm olan transaction rollback edilecektir. Bu, kurumg s s sal bir uygulamann veri btnlu iin ok nemlidir; Commit sinyali gelen u u ug c c o kadar hibir deiikliin kalc olmamas hayati nem tar. Cken bir srecin o c gs g o s o u ana kadar veri tabann ne durumda braktn bilemeyiz, belki yaplacak SQL g 308

Beklemeden Kitlemek ilemlerinin sadece yars gerekletirilebilmitir. Bu durumdaki bir transacs c s s tion commit etmek, intihar demek olurdu! Mesel mteri rneine dnersek, a us o g o belki mterinin hesabnda para eksiltilmi, ama teki hesabna para eklenus s o emeden sre kmtr. Bu durumdaki bir transaction commit edilecek olsa, u c co us u mteri para kaybetmi olurdu! Bu tolere edilecek bir davran deildir. Bu seus s s g beple veri taban urnleri, ken bir srecin balantsn ve onun iindeki olduu u co u g c g transaction otomatik olarak rollback ederler. Ayrca tm modern veri taban urnlerinde transaction ve satr seviye kilit u u (row level lock) yaknen (birebir) balantldr. Syle ki; Eer bir satr uzerinde g o g UPDATE komutu ile gncelleme yaplmsa ve o transaction commit edilmeden u s ikinci bir UPDATE ayn satr gncellemeye kalkarsa, ikinci UPDATE birincinin u bitmesini bekleyecektir. Bitmek, daha nce belirttiimiz gibi, ya commit ya da o g rollback ile olmas mmkn bir ilemdir. u u s Ikinci UPDATE birinci bittii anda ileme konur ve o da bittiinde (commit g s g ya da rollback ile) geri gelir.

9.4

Beklemeden Kitlemek

Eer bir satr uzerinde kilit olmasn bekliyor, ve o kilit uzerinde taklmak g istemiyorsak, Oraclea o satr beklemeden kitlemeyi denettirebiliriz. Bunun iin; c
SELECT ... WHERE .. FOR UPDATE NOWAIT;

komutu kullanlr. Normlde SELECT FOR UPDATE komutunun kitleme davran, a s UPDATE komutununki ile ayndr. Ayrca NOWAIT eki, Oraclea eer bir kilit mevg cutsa beklemeden dnmesini syleren ek bir davran salar. o o s g Kilit beklemeden dnme yntemi toptan (batch) ilem yapan programmz o o s iin faydal olabilir. Mesel, her yeni GARAGEn altndaki her CAR nesnelerini c a bir ekilde ilemden geirmemiz istense ve uygulamamzn ok sreli (multi s s c c u c process) bir hlde almas istense, birden fazla srecin ayn tablo uzerine a c s u akn etmesi bir problem dourabilirdi. Paylam mekanizmas olarak GARAGE g s tablosu uzerinde SELECT FOR UPDATE NOWAIT ile alnan bir kilidi kullanrsak, ikinci, ucunc, vs. gelen sreler, beklemeden dnecekler, ve baka bir GARAGE u u c o s satrn kilitlemeye (kapmaya) uraacaklardr. g s Bylece bir GARAGE satrnn ilenmekte olduunu, uzerinde kilit olmasndan o s g anlayabiliriz. Alternatif olarak GARAGEa STATUS adnda bir kolon eklesek (zerinde u ileniyor,ilenmiyor gibi bir durum kodu kullanlarak), bu iimize yaramazd, s s s unk bir GARAGE ilemekte olan srecin kme durumunda, STATUS kolonu c u s u co eski hline getirilemeyecei iin, srekli ileniyor modunda gibi gzkecekti; a g c u s o u Halbuki kilit kullanld artlarda, srecin ku satr kilidinin otomatik olarak g s u co us braklmas anlamna gelecek, bylece yeni bir srecin ayn satr kitleyerek o u ileme kalnan yerden devam etmesine izin verilecebilecektir. Altta bahsedilen s toptan ilemin taklit kodunu (pseudocode) gryoruz. s ou
list = run_query(SELECT * from GARAGE);

309

9. VERI TABANLARI
for garage in list begin result = SELECT * FROM GARAGE + where ID = garage.id FOR UPDATE NOWAIT; if (result.size == 0) begin continue; else process_cars(garage); end; end

9.5

Kurmak

Bu blmde MySQL, PostgreSQL ve Oracle SuSe Linux uzerinde nasl kuou racamz greceiz. g o g

9.5.1

Linux Uzerinde Oracle

o Ilk nce, tm Oracle iletim seviyesi ilemlerini yapmak iin, oracle adnda bir u s s c Unix kullancs yaratmanz gerekiyor. Aadaki komutlar root olarak iletin. s g s
groupadd dba groupadd oinstall groupadd oper mkdir /home/oracle chown -R oracle /home/oracle useradd -g oinstall -G dba,oper oracle passwd oracle

Oracle, bir Unix kuruluundan belli ayarlar bekler, sistemin paketten kt s c g haliyle alsmayacaktr. SuSE Linux iin kernel seviyesinde yaplmas gereken c c ayarlar aada verilmitir. s g s Liste 9.1: /etc/sysctl.conf
kernel.shmall = 2097152 kernel.shmmax = 2147483648 kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 fs.file-max = 65536 net.ipv4.ip_local_port_range = 1024 65000

310

Kurmak Bu ayarlarn ileme konmas iin, SuSE Linux uzerinde /sbin/chkconfig boot s c .sysctl on komutu iletilmelidir. s Artk kurulu ilemini balatabiliriz. Bunun iin oracle kullancs altndan s s s c ./runInstaller komutunun iletilmesi gerekiyor. Bu program, X Windows s (10.8) uzerinden alan grsel bir programdr. Olaan deerleri kullanmak iin c s o g g c Next dmesine basarak geebilirsiniz. Cou Oracle kuruluu iin olaan ug c g s c g deerler uygundur. Daha ileri trden kurulular iin, DBAinize dann. g u s c s Oracle iler kodlarnn kuruluu bittikten sonra, sra bir veri taban yarats s maya geliyor. Oracle kurulu srasnda kurulan veri taban yerine bir bakasn s s yaratmak isterseniz, dbca grsel programn balatarak istediiniz taban yaratao s g bilirsiniz. Ayn ekilde, taban iin bir isim vererek, geri kalan olaan deerler s c g g ile taban yaratmak mmkndr. u u u Bu aamada en nemli ve deiik yapmanz gereken ilem, taban seviyesinde s o gs s Trke karakter destei iin yapmanz gereken deiikliktir. Sekil 9.3, istenilen u c g c gs karakter destei iin kullanlmas gereken ekran ve seilmesi gereken deerleri g c c g gsteriyor. o

Sekil 9.3: Trke Karakter Set Destei u c g Taban yaratldktan sonra, /etc/oratab dosyasna girin, ve burada, yeni yarattnz taban iin olan satrn en sonundaki deeri N deerinden Y g c g g deerine getirin. Bu dosya, dbstart komutu kullanldnda hangi veri tag g banlarnn balatlmas gerektiini kontrol eder. Bundan sonra oracle kuls g lancsndan dbstart kullanarak tabannz balatabilirsiniz. s
oracle@linux:~> dbstart

311

9. VERI TABANLARI
SQL*Plus: Release 10.1.0.3.0 - Production on Mon Jun 6 15:07:36 2005 Copyright (c) 1982, 2004, Oracle. All rights reserved. SQL> Connected to an idle instance. SQL> ORACLE instance started. Total System Global Area 285212672 bytes Fixed Size 778776 bytes Variable Size 95428072 bytes Database Buffers 188743680 bytes Redo Buffers 262144 bytes Database mounted. Database opened. SQL> Disconnected from Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Production With the Partitioning, OLAP and Data Mining options Database "orcl" warm started.

Bu taban uzerinde eer admin seviyesi ilemler yapmak isterseniz, dbcaden g s admin iin verdiiniz ifreyi kullanarak Oraclea balanabilirsiniz. Mesel, yeni c g s g a bir kullanc yaratmamz gerekse:
sqlplus system/<ifre>@orcl s create user kitapdemo identified by kitapdemo default tablespace users; grant dba to kitapdemo;

Sifre olarak kitapdemo metnini kullanacak, ve olaan tablo depolama yeri (ta g blespace) users olacak kitapdemo adnda bir kullanc yarattk, ve bu kullancya DBA haklar verdik. Dier bir makinadan yeni tabannza balanmak iin, o makinada Oracle g g c Client kuruluunu yapm olmanz gerekir. Bu kuruludan sonra Oracle dizinini s s s bulun (mesel ORACLE_HOME), ve bu dizin altndaki tnsnames.ora dosyasna a servis makinanz vere yeni Oracle tabannz hakknda bilgileri ekleyin: Liste 9.2: ORACLE HOME/ora92/network/admin/tnsnames.ora
SAMPLE = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.1)(PORT = 1521)) ) (CONNECT_DATA = (SID=SAMPLE) )

312

Kurmak
)

Burada belirtilen HOST, veri tabann barndran makinann IP adresidir. SID, dbca ile yarattnz veri tabannn ismidir. Artk makinanzdan sqlplus g komutunu kullanarak uzaktaki tabana balanabilir ve tablolar yaratp veri g ekleyebilirsiniz. Daha nce yarattmz kitapdemo kullancsn kullanalm. o g
sqlplus kitapdemo/kitapdemo@orcl create table vsvs (kolon1 varchar2(20) ..); ...

9.5.2

Linux Uzerinde PostgreSQL

SuSE Linux uzerinde PostgreSQL kurmak iin, ncelikle http://www.post c o gresql.org/ftp/binary/v8.0.2/linux/suse/sles8-i386/ adresinden postgresql-libs-8.0.2-1.i586.rpm postgresql-8.0.2-1.i586.rpm postgresql-server-8.0.2-1.i586.rpm dosyalarn indirin ve bu dosyalar root kullancs tarafndan rpm -i ile, teker teker ve gsterildii srada, iletin. o g s Bir PostgreSQL servisini kullanmak iin ilk yapmanz gereken, veri taban c alann sfrlamaktr. Fakat bunun iin kullanlacak initdb komutunu root c olarak iletmenize izin verilmez. PostgreSQL servisini iletmek iin yeni bir s s c kullanc yaratmanz gerekiyor. Unix kullancs root olarak unlar iletin. s s
mkdir /home/postgres useradd -d /home/postgres -s /bin/bash -p postgres postgres chown -R postgres /home/postgres

Bu yeni kullanc olarak sisteme girin.


su - postgres initdb -E UNICODE /usr/bin/pg_ctl -D /var/lib/pgsql/data -l logfile start createdb test

Yukardaki komutlarla, veri taban alann sfrladk ve Trke karakter kulu c lanacak test adl bir veri taban yarattk. En son olarak veri taban servisini balattk. s 313

9. VERI TABANLARI Simdi demo adnda yeni bir kullanc ekleyelim. Sorulan y/n sorularna En ter tuuna basarak geebilirsiniz. s c
postgres@linux:~> createuser -P Enter name of user to add: demo Enter password for new user: <biz burada demo deerini kullandk> g Enter it again: <..> Shall the new user be allowed to create databases? (y/n) Shall the new user be allowed to create more new users? (y/n) CREATE USER

PostgreSQLn alt sistemi ve servisini JDBC uzerinden gelecek d balantlara c s g s g amak iin, aadaki dosyalar deitirmeniz gerekiyor. c c s g gs Liste 9.3: /var/lib/pgsql/data/postgresql.conf
listen_addresses = *

Liste 9.4: /var/lib/pgsql/data/pg hba.conf


host all all 192.168.0.2 255.255.255.255 trust

satrn ekleyin. Bu satrda belirtilen 192.168.0.2 IP deeri, balanan bilgisag g yarn IP adresi olmaldr. Bu deerlerin etkiye gemesi iin, komut satrnda g c c postgres kullancs olarak
/usr/bin/pg_ctl restart

komutunu ileterek yeni deerlere ileme sokabilirsiniz. Ayrca, PostgreSQL s g s kullancsnn (rneimizde demo) bir tabloya eriebilmesi iin o g s c
grant all on <tablo ismi> to public;

komutunu vermeyi unutmayn.

9.5.3

Linux Uzerinde Mysql

MySQLi Linux ve Solaris uzerinde kurmann en salam yolu, RPM deil, tar g g .gz sonekli bir dosyay kullanp bu dosyay uygun yere amanzdr. Bunun c iin, http://dev.mysql.com/downloads/ adresinden istediiniz genel srm c g uu numarasna giderek, buradan Linux (non RPM package) downloads altndaki Standard satrndan Pick A Mirrora tklayarak mysql-standard-xxx-pc -linux-i686.tar.gz gibi bir dosyay indirmeye balayn. Indirdikten sonra s aadaki komutlar root olarak srasyla uygulayn. s g
tar xvzf mysql-standard-4.0.23-pc-linux-i686.tar.gz ln mysql-standard-4.0.23-pc-linux-i686 -s /usr/local/mysql cd /usr/local/mysql

314

Kurmak

groupadd mysql useradd -g mysql mysql ./scripts/mysql_install_db --user=mysql chown -R root . chown -R mysql data chgrp -R mysql . bin/mysqld_safe --user=mysql & bin/mysql

TAR dosyasn atk, veri tabann hazrladk ve mysqld_safe ile veri taban c servisini balattk. En son komut ile, mysql komut satrna girmemizi salad. s g Bu komut satrnda ilk i olarak MySQL root kullancs iin bir ifre tanmlamanz s c s iyi olur. Altta bu ifreyi admin olarak setik. s c
mysql> SET PASSWORD FOR root@localhost = PASSWORD(admin);

Artk, MySQL komut satrna salt bin/mysql ile deil, bin/mysql -p ile girmemiz g gerekiyor. Sifre sorulunca admin girebiliriz. En son yaplmas gereken, root kullancsn d makina balantlarna amaktr. s g c Bunu yapmazsak, MySQLe sadece localhosttan balanabiliriz, ki bu da g datk bir uygulama iin pek faydal olmazd. g c
mysql> GRANT ALL ON *.* TO root@% -> IDENTIFIED BY admin -> WITH GRANT OPTION;

Eer mysqld_safe balamaz ise, mysqld programn deneyebilirsiniz. Balattktan g s s sonra mysql komutu problem kartrsa, mesel mysql.sock dosyasnn bulunac a mamas gibi, o zaman bu dosyay istenen/aranan yere bir Unix sembol balant g (symbolic link) ile balayarak tekrar deneyeblrsnz g c
ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock

315

9. VERI TABANLARI

316

Bl m 10 ou

Unix

Bu Bl mdekiler ou Unix felsefesi Sreler u c Kullanclar Aralar c

317

10. Unix

nix bir gzelliktir. Unix, en az ile en fazla yapmann en baarl rnei, u s o g bir yaln tasarm abidesidir. Unix bize bir yazlm mimarinin nasl olmas gerektiinin en plak ekliyle anlatr, tarif eder. Piyasada bu kadar g c s zaman kalabilmi, ve kritik uygulamalarda servis tarafn pazar payn tamas men eline geirmi olmasnda bu doru tasarmn byk etkisi vardr. Aslnda, c s g u u kitabmzn dier blmlerinde nerdiimiz mimariler ve teknolojiler, ruh olarak g ou o g Unix felsefesine birebir uyumludurlar. Cunk biz bu felsefenin takipileri, ve u c bu felsefeyi projelerimizde kullanabilmi sektrn elemanlaryz. s ou Peki bu felsefe nedir? Unix, tasarm bakmndan zel hallerden kanm bir iletim sistemidir[14, o c s s sf. 77]. Herkes iin herey olmaya almaz, ama hereyin yaplabilmesine izin c s c s s verecek en baz altyapy salar. Bunun yan etkilerinde bir tanesi, altyapnn g uygulamalardan net bir ekilde ayrlmas, ve bylece uygulamann bir bakas s o s ile rahat bir ekilde deitirilebilmesidir. s gs Mesel komut satr program, DOSta olduu gibi iletim sisteminin iine a g s c sokuturulmamtr. Bu sadece bir grevten ibarettir, ve Unixte ayr program s s o ayr sre altnda (aynen dier uygulamalar gibi) alr. Unixte bireyler u c g c s s yapan herey bir sre, bir ilemdir[14, sf. 77]. Bu ayrlk sayesinde Unix s u c s dnyasnda birok komut satr alternati gelitirilmitir (bash, sh, tcsh, ksh) u c s s ama DOS dnyasnda hla sadece tek bir komut satr mevcuttur. u a Unix iletim sisteminin yaln yaps, insanlar en bata en ok artan, s s c s s ve sonra merakn uyandran faktrlerden biridir. Unixde neredeyse herey o s alt temel ilemle yaplr, ki bunlara sistem arlar ad verilmitir; Bu alt s c g s temel sistem arsyla neredeyse hereyi gelitirebilirsiniz. Bu alt temel ary c g s s c g kavrarsanz, Unixi kavram olursunuz[14, sf. 88]. s Yni Unixin gzelliklerinden birisi, karmak eyler oluturmak iin karmak a u s s s c s ara birimlere gereksinmediinizi anlam olmasdr. Basit eylerin etkileimiyle g s s s istediiniz kadar karmak yaplar oluturabilirsiniz. Yapmanz gereken, karmak g s s s problem zme yaplar yaratmak iin basit ilemler arasnda iletiim kanallar co c s s (pipe) oluturmaktr[14, sf. 78]. s Temel bilimlerde de bir ziksel olay aklayacak matematiksel kuramlar c arasnda seim yaplrken aranan zelliklerden birisi basitliktir. Bilim dnyasna c o u yn veren nemli bir deyi olan Occamn Usturas der ki: Mevcut alternato o s ier arasnda en basit aklamay seiniz. Temel bilimler, tarih boyunca ve c c gnmzde bu desturu takip etmektedirler. Kurumsal programclkta da aynen u u u temel bilimlerde olduu gibi, basitlik esastr (Kural #1). Bilgisayar dnyasnda, g u kark yapy yaratmak programcnn iidir (uygulama yazmak), kyasla temel s s bilimler karklktan basit aklamaya doru gitmeye alr; Fakat felsefe her s c g c s iki taraf iin ayndr. Sadece gidilen yn deiiktir. c o gs 318

Unix Aralar c

10.1

Unix Aralar c

Bahsedilen trden basit yap, Unix iin birok aracn yazlmasn salamtr. u c c g s Unix felsefesine uyumlu olan Unix aralar, aynen iletim sistemin kendisinin c s olduu gibi, sadece bir ii, en iyi ekilde yapmak iin yazlrlar. g s s c Kitabmzn ana amac kurumsal yazlm sektrde alan programclar ve o c s teknik liderlere yardm etmek olduu iin, her Unix aracnn tm zelliklerini g c u o teker teker anlatmayacaz. Bizim faydal olduunu dundumz bilgi, ihtiyalar g g us ug u c nda hangi Unix arac ve aralar dizisinin (ou zaman iletiim kanallar ile sg c c g s birkan birbirine balayarak) kullanlmas gerektiini anlatmaktr. c g g

10.1.1

Komut Birletirme s

Unix aralar arasnda iletiim kanal oluturmak iin | iareti kullanlr. c s s c s Mesel eer command1 ve command2 adnda iki Unix programmz olsa ve coma g mand1in ktsn command2ye gndermek istesek, o zaman c o
command1 | command2

komut srasn kullanrdk. Burada en son iletilecek komut olan command2nin s kts (byk ihtimalle) ekrana baslacaktr. c u u Ekrana baslacak bir kty bir dosyaya ynlendirmek istersek, > iareti c o s ya da >> iaretinden sonra bir dosya ismi kullanlr. > iareti, yeni bir s s dosyaya yazmak, >> ise mevcut bir dosyaya eklemek iin kullanlr. c
command1 | command2 >> /tmp/out.txt

Bu iletim srasna gre, nce command1 arlacak, onun kts command s o o c g c 2ye girdi olarak verilecek ve command2nin kts /tmp/out.txt adl dosyaya c yazlacaktr.

10.1.2

S reler u c

Unixde ilettiiniz her program bir sre (process) hline gelir. s g u c a Listelemek O ana kadar sizin balatm olduunuz sreleri grmek istiyorsanz, ps komus s g u c o tunu kullanabilirsiniz. Suna benzer bir kt gelecektir c
PID 452 1656 PPID 1 452 PGID 452 1656 TTY UID STIME COMMAND con 1004 11:55:54 /usr/bin/bash con 1004 11:55:58 /usr/bin/ps

Bu listedeki PID kolonu srecin kimlik numarasdr. Eer sistemde, sizin dahil, u g tm kullanclarn balatm olduu sreleri grmek istiyorsanz, u s s g u c o
ps -eaf

319

10. Unix komutunu kullanabilirsiniz. Bu sefer daha byk bir liste gelecektir (unk herkesin u u c u srelerini grmek istediniz). u c o u Old rmek Bir sreci ldrmek iin PID nosunu renip o numaray kullanarak u komutu u o u c og s kullanabilirsiniz.
kill -9 <PID>

Eer bir program ps -eaf listesinde kan bir isme gre ldrmek istiyg c o o u orsanz, ou Unixde bunun iin bir pkill komutu vardr. Ama dikkat edin! c g c Mesela pkill java gibi bir komut, sistemde ileyen tm Java programlarn s u ldrr; Eer ayn makinada birden fazla kii Java uygulamasn test ediyor o uu g s ve siz de root iseniz, insanlarn almasn etkileyebilirsiniz. Bu yzden bu c s u komutu dikkatli kullann.

10.1.3

Dosyalar

Ekrana Basmak cat ile bir dosyay tamamen ekrana basabiliriz. Eer dosyay ksm ksm grmek g o istiyorsak, less <dosya> komutu ie yarar. less ilerken bir sonraki sayfaya s s gemek iin SPACE, geri gitmek iin b, en tepeye gitmek iin g, ve en alta gitmek c c c c iin G tular kullanlabilir. q ile less programndan kmak mmkndr. less c s c u u u komutu, ondan nce gelmi olan more komutundan daha kuvvetlidir, tavsiyemiz o s less kullanmanzdr. Buradaki isimlendirme esprisi, raslantsal bir ekilde (ya s da bilerek) Unix felsefesinin zn yine ortaya koymutur: (daha az anlamna o u u s gelen) less komutu (daha fazla anlamna gelen) moredan daha kuvvetlidir! c Dosya Iinde Bulmak Herhangi bir dizin altndaki bir veya daha fazla dosyalar iinde bir kelimeyi c aramak istiyorsanz, grep komutunu kullanabilirsiniz.
grep aranan kelime *.java

gibi. Bu komut sonucundan bulunan dosyalar listenecektir. Dosya Bulmak Bir isim dzenine uyan tm dosyalar bulmak iin, find komutu kullanlr. u u c
find /usr/local -name *.java

Bu komut /usr/local seviyesinden balayarak sonu *.java ile biten tm s u dosyalar bulup geri getirecektir. find komutundan hemen sonra gelen dizin, aramann nereden balayacana iaret eder. s g s 320

Unix Aralar c Eer bulunan dosyalar uzerinde bir komut iletmek istiyorsanz, find ile g s xargs komutunu birbiri ile iletiim (pipe) kurdurarak kullanabilirsiniz. Mesel s a sonu *.java ile biten tm dosyalar ekrana basmak iin u c
find . -name *.java | xargs cat

c Dosya ve Dosya Iinde Bulmak s Ite Unix felsefesinin bir rnei: Orendiimiz iki komutu birletirerek, bir o g g g s dizinden balayarak hem o dizin hem de altndaki tm dizinler altnda belli s u bir dzene uyan dosyalar iinde bir kelimeyi aryorsak, u c
find . -name *.java | xargs grep -l aranan kelime

komutunu kullanabiliriz. -l seenei, bulunan dosya ismini ekrana basmak iin c g c kullanlr. Dosya ve Dizin B y kl kl kleri u u u u Bir dizinin ya da tek dosyann ne kadar yer tuttuunu anlamak iin, du kulg c lanlr. Tek bana kullanlnca, komutun kullanld dizin altndaki her dizinin s g ne kadar byk olduu ekranda gsterilecektir. Eer du -s kullanlrsa, bu alt u u g o g dizin byklklerinin toplam alnacaktr, yni tek say geri gelecektir. u u u a Eer bir dizinin altndaki hangi alt dizinin en fazla yer tuttuunu merak g g ediyorsak (ki bu bazen ok ie yarar), o zaman, dudan gelen sonular baka c s c s bir Unix komutuna iletmek gerekecektir. Bu dier komur, sraya dizme (sort) g komutudur.
du | sort -n

Bu komut dizinleri byklk srasna gre kcukten bye doru dizer. Peki u u u o u u ug g sort komutu, dudan gelen sonu uzerinde ilk kolona (bykle) bakacan c u u ug g nereden bildi? Cunk dudan gelen sonularda byklk, ilk kolonda idi, ve u c u u u sort, satrlar ilk karakterlerinden balayarak dizmek iin yazlmtr. s c s Satr Says Bir dosyann ka satr ve ka kelime ierdiini anlamak iin wc kullanlr. Tek c c c g c bana wc bir dosyadaki satr, kelime saysn beraber gsterir, ayr ayr bilgi s o almak iin wc -l, sadece satr saysn, wc -w kelime says iin kullanlabilir. c c c Ierik Deitirmek gs Bunun iin Perl kullanacaz. Komut satrnda Perl, hem yerinde deiiklik ve c g gs hem de dzenli ifade kullanabilmektedir. u
perl -pi -e s/filan/falan/sg

321

10. Unix s komutu, filan ile falan kelimesini deitirir. I bittikten sonra bir yedek gs dosyasi (.bak) bulacaksnz.

10.2

Kullanclar

Unixde her kullanc /etc/passwd dosyasnda tutulur. Bu dosyaya erimeye s sadece root kullancnn hakk vardr. Projenizde genelde programclara root eriimi verilmez, ama teknik lidere bu hak tannr. Bu, Unixi daha yeni renmekte s og olan programclarn yanllkla sistemi hasar vermesine kar yaplr. s s En gl kullanc olan root, birok admin odakl ii yapabilir, bu yzden uc u c s u haklar tm dier kullanclardan daha fazladr. Mesela root, herkesin srecini u g u kill ile ldrebilir. Dier kullanclar byle bir ey yapmaya kalksa, sistem o u g o s s onlara izin vermeyecektir. Bir kullancn giri yaptnda hangi komut satr progamn (shell) kuls g lanaca (birok seenek mevcuttur), /etc/passwd iinde tanmldr. Bu shell, g c c c kullanc yaratlrken useradd komutuna parametre olarak verilir;
useradd -d /home/user123 -s /bin/bash user123

Parametre -d kullanc (HOME) dizini, -s ise shell tipi iin kullanlr. c Bir kullanc sisteme girdiinde, ya da bir xterm, yeni bir shell balattnda, g s g kulland shell trne gre iletilen ayar dosyas deitiktir. Shell sh, ve bash g uu o s gs ise, nce /etc/profile scripti, sonra kullanc HOME dizini altndaki .proo file iletilir. Eer admin isek ve tm kullanclarn etkilenecei trden bir s g u g u deiiklik yapmak istersek, bunu /etc/profile iinde yaparz. Her kullanc gs c kendi isteine gre .profile deitirebilir. g o gs Her kullanc iin bir HOME deikeni mevcut olacaktr. Bu deikeni ekranda c gs gs gstermek iin echo \$HOME komutunu kullanabilirsiniz. o c Eriim haklarn daha geni bir kategori uzerinden idare edebilmeye ads s minler iin gereklidir. Bu ihtiyaca cevaben Unix, kullanc gruplar kavramn c destekler. Bir kullanc birden fazla gruba dahil olabilir. Bir kullancy useradd ile yaratrken hangi gruba dahil olmasn istediinizi biliyorsak, -g seenei ile g c g bu grubu tanmlayabiliriz. Sisteme bir grup eklemek iin groupadd komutunu c kullanmak gerekiyor. Eer useradd ilemi bittikten sonra kullancy bir gruba dahil etmek isg s tersek, /etc/passwd dosyasn gncelleyerek bunu baarabiliriz. Bu dosyada u s kullancnn tanmland satr bulup, oradaki grup listesine yeni grup nosunun g eklenmesi gerekiyor. Grup ismine bakadar grup numarasn bulmak iin /etc c /group dosyasna bakabiliriz. Bir kullanc hangi gruba dahil olduunu grmek isterse, komut satrndan g o groups komutunu vermesi yeterlidir. Sper kullanc root bakalarnn gruu s plarna bakabilir, bunu iin groups <username> komutunu kullanr. c 322

Scripting

10.2.1

Dosya Haklar ve Kullanclar

ls -al ile bir dizindeki tm dosyalarn kullanm haklarn grebilirsiniz. u o


drwxr-xr-x 9 burak None 0 Jun 14 15:57 Example -rwxr-xr-x 9 burak None 0 Jun 14 15:57 Ex.txt

Bu listede iki birim gryoruz; Example ve Ex.txt. Her dosya ya da dizin ou iin onun olduu satrn bana bakarsak, drwxr-xr-x gibi bir tanm grrz. c g s ouu Example dizini rnek alalm. drwxr-xr-x ne demektir? o Bu tanm kelimesini, ncelikle zihnimizde drde blmemiz gerekir. Yni o o o a biraz nceki rnek, una dnur: d, rwx, r-x, ve r-x. Bu blmlerden tek o o s o us ou hneli birinci blm birimin dosya m, dizin mi olduunu belirtir. d dizin, a ou g dosya demektir. Ondan sonra gelen uc byk grup, srasyla kullanc (user), grup (group) u u ve tekiler (others) iindir. Kullanc, kullancn kendisi iin geerli olan haklar, o c c c grup, kullancnn iinde olduu gruptaki herkes iin olan haklar, tekiler ise c g c o bunun haricinde kalan herkes iin geerli olan haklardr. Bylece kendinize c c o verdiini bir hakk, grubunuzdaki bir kiiye vermemeyi (mesel) seebilirsiniz. g s a c Her kelime grubu iindeki haklar, unlar olabilir. O dosyay okumak (read), c s deitirebilmek (write), ve iletebilmek (execute). Okumak iin r, deitirebilmek gs s c gs iin w ve iletebilmek iin x karakteri kullanlr. Eer bu haklar var ise onun c s c g karakteri, yok ise - karakteri kullanlacaktr. Haklarn karakterleri bir grup iinde hep ayn yerlerde karlar; Grubu iinde c c c r hep birinci srada, w ikinci srada, ve x ise ucunc srada olacaktr. u Dosya Kullanm Hakk Vermek ve Almak Hak vermek iin chmod komutu kullanlr. Kullanm chmod <haklar> dosya c eklindedir. Bir dosyann tm haklarn ayn anda set edebilen say yntemi yers u o ine (mesel chmod 777 file.txt) biz, + ve - ile hak ekleme karma yntema c o ini tercih ediyoruz. Bunun iin, mesel kullancya okuma hakk vermek iin c a c chmod u+r <dosya> komutu kullanlr. Hak eksiltmek iin + yerine - kullanmak c gerekir. Ayn ekilde gruba okuma hakk vermek iin chmod g+r <dosya> kuls c lanlr. Oteki kullanclar iin o, ve her kullanc herkes iin a kullanlmaldr. c c a ile tm kullanclara (u, g, o) belli bir hakk ayn anda verme yeteneine u g kavuuyoruz. s

10.3

Scripting

Bir arada ilemesini istediini komutlar bir dosyaya koyup, bir script olarak s g iletebilirsiniz. Scriptleriniz herhangi bir shell iin yazabilirsiniz, ama bizim s c tavsiye ettiimiz shell, her Unix sisteminde olmas garanti olan sh shellidir. g Bir scripti iletmek, kurumsal programclar tarafndan Unixin en az anlalan s s ve en son tamamiyle renilen tekniklerden biridir. Bir script iinde set og c 323

10. Unix edilen deikenler, aran shelli nasl etkileyecektir? Bir scripti birka ekilde gs c g cs arma ekillerinden hangisi uygundur? c g s Elimizde script.sh adnda bir script olduunu farz edelim. Bu script iinde g c unlar olsun; s
VAR1=/tmp/vs/vs command1 command2

Bu scripti u ekilde iletebilirsiniz. c s s 1. sh script.sh: Scriptin ilemesi tamamlandktan sonra, aran shell, s c g ieride tanmlanan ve set edilen VAR1 gremez. c o 2. script.sh: Avantaj, iletmek iin shell uzerinde sadece tek kelime kuls c lanmasdr. Bunun iin script.sh dosyasnn en ust satrna #!/bin/sh! c ibaresini eklemeliyiz. Bir de, iletmeden nce (sadece bir kez) chmod u s o +x shell.sh ile bu dosyay sadece kendi kullancmz iin iletilebilir c s hle getirmeliyiz. Bundan sonra komut satrndan uygulanacak tek bana a s c s o g shell.sh komutu, alacaktr. Fakat VAR1, aynen biraz nce olduu gibi, aran shell tarafndan gzkmeyecektir. c g o u 3. . shell.sh: Bu kullanm, Unixde kaynaklama (sourcing) yapar, yni a script sanki iindeki her satr, komut satr uzerinde elle yazlyormu gibi c s iletilir. Ayrca daha nceki iletim stillerinde, shell.sh arm yeni bir s o s c g sre altnda iliyordu, ve orada yaratlan her deiken yaplan her i o u c s gs s sre bitince onunla beraber lyordu. Kaynaklama ynteminde durum u c ou o deiiktir. Bu yntemde, arm geri gelince VAR1in deeri aran shell gs o c g g c g tarafndan grlyor olacaktr. o uu Ayrca eer 1. ve 2. yntemlerde de shell.sh iledikten sonra ieride tanmlanan g o s c ve set edilen deikenlerin dardan (aran shell iinden) grlmesini istiygs s c g c ou orsak, o zaman bu yntemlerde script iinde deikene bir deer set ettikten o c gs g sonra onu darya ithal etmeliyiz; Bourne shell (sh) iinde bu export VAR1 s c komutu kullanlarak yaplr.

10.4

s Makina Balaynca Program Iletmek s

Baz programlarn bilgisayar ald zaman otomatik olarak balamasn isc g s tiyor musunuz? Mesela, bir Linux makinasn tamamen Oracle icin ayrdk, ve Oracle, bilgisayar alr almaz balamal. Sistem idarecisi olarak her seferinde c c s oracle kullancsna girip, durdurma/balatma yapmak istemiyoruz.. s Unixte bu iler, dier pek ok eyde olduu gibi, metin bazl ayar dosyalar s g c s g uzerinden yaplyor. Bir Unix sisteminde bilinen, ve nemli dizin blgeleri vardr. o o Mesela /etc/ dizini bunlardan biridir. Cogu Unix versiyonu, /etc/ altna 324

MAKINA BASLADIGINDA PROGRAM ISLETMEK onemli ayar dosyalarn koyar. Yni, bir script ile /etc/ altndaki dosyalar a deitirirseniz, sistemin ileyii deiecektir. Dikkatli olmamz isabetli olacaktr. gs s s gs Durdurup balatma ayar dosyalar /etc/rc.d dizini altndadr. Buraya s girip ls -al iletirseniz, aadaki tabloyu grebilirsiniz. s s g o
drwxr-xr-x 10 root drwxr-xr-x 43 root drwxr-xr-x 2 root -rwxr-xr-x 1 root drwxr-xr-x 2 root drwxr-xr-x 2 root drwxr-xr-x 2 root drwxr-xr-x 2 root drwxr-xr-x 2 root drwxr-xr-x 2 root drwxr-xr-x 2 root -rwxr-xr-x 1 root .. .. root root root root root root root root root root root root 4096 4096 4096 3219 4096 4096 4096 4096 4096 4096 4096 3200 Sep Sep Sep Jul Apr Apr Apr Apr Apr Apr Apr Sep 15 01:09 . 15 01:23 .. 6 15:51 init.d 10 2001 rc 4 13:25 rc0.d 4 13:25 rc1.d 4 13:25 rc2.d 4 13:25 rc3.d 4 13:25 rc4.d 4 13:25 rc5.d 4 13:25 rc6.d 15 01:08 rc.local

rc kelimesinden sonra gelen say, balama seviyesini belirtir. Bir Linux s makinasn deiik balama seviyesinde balatmamz mmkndr. Mesel ok gs s s u u u ac nemli bir sistem bakm gerekiyorsa ve bu bakm yaplrken hibir kullancnn o c sisteme balanamamas lzm ise, balama seviyesi 0 yada 1, bu i iin kulg a s s c lanlabilir. Bu seviyelerde kullanc giri programlar salanmamtr, ve bylece s g s o sadece root sisteme terminalden girerek istedii bakm yapabilir. g Sistemi 4. balama seviyesinde balatmak demek, rc4.d altna girip, oradaki s s balatma scriptlerini iletmektir. Simdi rc4.d altnda ne var grelim. s s o
lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx lrwxrwxrwx 1 1 1 1 1 1 1 1 1 1 1 1 1 1 root root root root root root root root root root root root root root root root root root root root root root root root root root root root 14 16 16 15 18 18 17 16 17 17 18 16 15 14 Apr Apr Apr Apr Apr Apr Apr Apr Apr Apr Apr Apr Apr Apr 2 2 2 2 2 2 2 2 2 2 2 2 2 2 13:36 13:38 13:38 13:34 13:34 13:34 13:34 13:33 13:36 13:37 13:33 13:34 13:34 13:34 K74ntpd K74ypserv K74ypxfrd S05kudzu S08ipchains S08iptables S10network S12syslog S13portmap S14nfslock S17keytable S20random S25netfs S26apmd

ipchains, syslog gibi programlar tandk gelebilir. Bu programlarn balatld s g noktay bylece grm oluyoruz. o o us Bir kavram daha kald: Baz scriptlerin K ile, tekilerinin S ile baladn o s g gryoruz. Bunun sebebi nedir? S Start icin K Kill iin kullanlr, yni ou c a 325

10. Unix balat ve durdur komutlardr. Eer Unix sistemi, rc4.d altndaki servisleri s g balatmak istiyorsa, nce, rc4.d altinda ls S* benzeri bir komut iletecektir. s o s Bu komut sadece S ile balayan scriptleri toplar. Sonra Unix sistemi, bu s scriptleri teker teker start kelimesini ekleyerek carr. Ayn ekilde sistem g s kapanrken, Unix ls K* benzeri komut iletip, durdurmak iin gerekli scriptleri s c toplar, ve onlar stop kelimesini ekleyerek arr. c g Peki niye arm yaparken start ve stop eklemek gerekiyor? Bunun c g sebebini script ieriine baktmzda greceiz. c g g o g
.. .. start() { echo -n >"Kaydediciyi baslatiyoruz.. " .. .. stop() { echo -n >"Kaydediciyi durduruyoruz.. " .. .. case ">1" in start) ;; eger Unix start kelimesi gondermis ise start ;; stop) stop eger Unix stop kelimesi gondermis ise ;; status) rhstatus ;; restart|reload) restart ;; .. ..

10.5

s Takvime Bal Program Iletmek g

Bir zamana, takvime bal program iletmek iin, cron program kullanlr. g s c cron program, crontab adnda bir ayar dosyas kullanr, ve bu dosya /etc/ crontab altnda bulunur. Bu ayar dosyasn ya direk (root olarak) ya da komut satrndan crontab -e ile edit etmeye balayabilirsiniz. Eer herhangi bir s g dosyann crontab dosyas olarak kullanlmasn istiyorsanz, crontab <file> komut ile bunu yapabilirsiniz. Bu durum genellikle crontab dosyasn CVS gibi bir kaynak kod idare sisteminde tutmak isteyenler iin gerekli olmaktadr. c Baz crontab seenekleri (ve alkal bir komut) unlardr: c a s 326

s Takvime Bal Program Iletmek g export EDITOR=vi crontabin hangi editr ile alacan kontrol eder. o c g vi yerine (eer varsa) emacs kullanabilirsiniz. g crontab -e: Ayar dosyasn gnceller u crontab -l: Ayarlar ekranda gsterir o crontab -r: crontab dosyasn siler crontab -v: Dosyay en son gncellediimiz tarihini gsterir u g o crontab dosyasnn her satr, deiik bir program ayarlamak iin kullanlr. gs c Bu her satrda, her kolon, zaman ayarnn belli bir blm iin kullanlr. Kolonou u c lar srasyla unlardr: Dakika, saat, ayn gn, ay, haftann gn ve yl. Her s u u u u kolon iin yldz * iareti, o ayarn dikkate alnmad anlamna gelir, mesel c s g a gn iin * var ise, o program her gn ileyecektir. Tablo 10.1 uzerinde izin u c u s verilen kolon deerlerini gryoruz. g ou Tablo 10.1: Crontab Kolon Deerleri g Alan dakika saat ayn gn u u ay haftann gn u u Izin Verilen Deerler g 0-59 0-23 0-31 0-12 0-7

Ornek bir crontab dosyas ise, altta grlmektedir. ou


SHELL=/bin/sh MAILTO=burak 5 0 * * * \$HOME/bin/daily.job >> \$HOME/tmp/out 2>&1 15 14 1 * * \$HOME/bin/monthly 0 22 * * 1-5 mail -s "Saat 10pm" burak%Burak,%%Nabersin?%

Her bir program tanmn teker teker tarif etmek gerekirse: o 1. Ilk nce iletilen programlarn hangi shelli kullanmas gerektiini tanmlyoruz. s g Burada seim /bin/sh olmutur. c s 2. Bu satrda, cron iledikten sonra onun ilettii dosyalarn ktsnn kime s s g c mail edileceini tanmlyoruz. Bu kii burada burak adndaki kullancdr. g s 3. Bu satrda, ilk takvimli program tanm yaplmtr. Bu program, her s gece yarsndan be dakika sonra her gn iletilecektir. \$HOME deikeni, s u s gs crontab dosyasnn sahibidir. 327

10. Unix 4. Her ayn ilk gnnde saat 2:15pmde \$HOME/bin/monthly adl program u u iletilecektir. s 5. Her i gn (Pazartesi ve Cuma arasndaki her gn, ve bu gnler dahil s u u u u olmak uzere) saat 10 pmde bu program iletilir. s

10.6

Network Durumu

netstat, sisteminizdeki network durumu gsterir. Genellikle kullanlma sebebi, o bir portun o anda kullanlp kullanlmadn anlamaktr. Sistemde kullanlan g tm portlarn listesini almak iin netstat -a kullanlr. u c

10.7

Yardm Almak

man komutundan sonra bir program ismi belirsek, bu program hakkndaki sistemde olan tm aklama ekrandan verilecektir. Unix dnyasnda man olduka u c u c fazla kullanlr, unk yeni rendiimiz (htta bazen eski bildiklerimizin bile) c u og g a komutlarn seeneklerini renmek iin, man komut_ismi kullanrz. c og c

10.8

X-Windows Kullanm

X-windows, Unix dnyasnda (Java appletlerden ok nce) grsel herhangi bir u c o o programn ekrann, penceresini, baka bir makinann monitornde gstermek s u o iin kullanlan tekniktir. c X-windows ile servis tarafnda bir program shell uzerinden iletip, penceresini s kendi sisteminize alabilirsiniz. Bunu yapabilmek iin ncelikle masast (aran) c o u u c g sisteminizde bir X ortam gerekecektir. Byle bir ortam, eer masast Linux o g u u ya da dier bir Unix ise kendiliinden olacaktr (kurulum srasnda X-windows g g setiyseniz). Windows uzerinde ise, Cygwin uzerinden X-windows kullanabilirsiniz. c Cygwin kurulumu iin A.6 blmne, Cygwin uzerinde X ortam kurulumu iin c ou u c A.13 blmne bakabiliriz. ou u Grsel program iletmek iin nce servis tarafna ssh ile balanlr. ssh o s c o g uzerinden X bilgilerinin geriye alnabilmesi iin, -X seenei kullanlmaldr. c c g
(desktop) \$ ssh host1 -l root -X

Servis sistemine girdikten sonra, servis makinasna ekrann nerede olduunu g sylememiz gerekiyor. Bunun iin DISPLAY evre deikenine ekrann makina o c c gs ismi (ya da IP numaras) sonuna :0.0 eklenerek verilir.
(host1) \$ export DISPLAY=desktop:0.0

Son basamak, masast tarafnda servis tarafna grsel bilgileri gndermesi u u o o iin izin vermektir: c
(desktop) \$ xhost +

328

X-Windows Kullanm Bu komut tm servis programlarna X bilgisi gndermesi iin izin verecektir. u o c Artk X programn balatabiliriz. Mesel xclock; s a
(host1) \$ xclock

Bu programn grnts olan bir saat, masast ekranmzda kacaktr. ou uu u u c

329

10. Unix

330

Bl m 11 ou

Proje Ynetimi o

Bu Bl mdekiler ou Karakterler Hata takip sistemi Kaynak kod idaresi Gelitirme ve test ortamlar s

331

11. PROJE YONETIMI

ger tasarm disiplini bilimden ziyade sanata yakn ise, sanata yaknlk yarmasnda birincilik madalyasn herhalde proje ynetimi disiplinine s o vermek gerekirdi. Cunk, yazlm mhendisliinde eya ounlukla in u u g s c g san (bazen de makinadr), ama proje yneticiliinde eya tamamen insandr. o g s Bu durum, proje ynetimi disiplininin anlatlmas ve sistemsel bir yapya oturo tulmas asnda zorluklar kartr, unk proje ynetim tekniklerini kullanan c c c u o insanlar farkl olduu gibi ynetimin hede olan insanlar da projeden projg o eye farkllk gsterirler. Insanlar hlen matematiksel ekilde anlatamadmza o a s g gre, proje ynetimi hakknda verilen her tavsiyenin kulaa gayri bilimsel o o g gelmesi normldir. Bu konu hakknda yazan herkes tavsiyelerini sadece kendi a perspektinden ve tecrbesine dayanarak anlatmaya mecbur kalmaktadr. Obu jektif, deneye dayal sonular henz literatrde grememekteyiz. c u u o Bu yzden, bu blmde anlatacamz proje ynetim teknikleri, bizim altmz u ou g o c s g projelerde iledii gzlenen subjektif teknikler olacaktr. Ornek olarak, tandmz s g o g ve sayg duyduumuz proje yneticilerinde iyi bulduumuz zellikleri sunacaz, g o g o g ve bunu mmkn olduu kadar projede alm dier insanlar da bu gre u u g c s s g o us katlm ise yapmaya gayret edeceiz. Teknik ve teknik olmayan arkadalar ile s g s iyi bir proje ynetiminin nasl olmas gerektii hakknda uzun yllar boyunca o g gr alveriinde bulunduk, bunlar da bu blmde paylamak istiyoruz. o us s s ou s Kiilere ek olarak, her projede kurulmas ve takip edilmesi gereken mekanik s srelerin proje ynetimi bakmndan nemli olduunu vurgulayp, rnekler u c o o g o gsterek anlatmaya alacaz. Sreler bize, ne yapacamz hatrlatc bir o c s g u c g zellik tarlar; Mekanik ileri srece devrederek (ve srele iletiimde tarafmz o s s u u c s yine mekanik dunceyi halleden beyin blgemize devrederek) programcln us o g daha yaratc ksmna bu ekilde korkmadan odaklanabiliriz. Mekanik ve nemli s o noktalar bize sre tarafndan hatrlatlacaktr. Mesel tasarm srecinin bir u c a u paras olarak kodlamaya balamadan nce mimariyi ortaya koyan bir belc s o genin yazlmasnn art konulmas, bir srece rnek olabilir; Bu belgeyi yazma s u o gereklilii, uzerimizde ileriyi dunmeye yolunda bir bask yaratr, ve bu bask g us iyi ve gereklidir. Bu rnekte sre, normlde yapmayabileceimiz bir eylemi o u c a g uzerimizde mecbur brakarak, bizi doru yne sevketmi ve yaratc duncem g o s us izi doru formata doru kanalize etmitir. g g s Ayn ekilde bir hata takip sreci, uygulamada test sonucu bulunan hatas u larn bir hata takip sistemine girilmesini mecbur klabilir, ve bylece hata o bulma, hata dzeltme ve kapatma gibi mekanik basamaklar bize hatrlatc u yardmclar hline gelirler. Biz tm hatalar hatrlayamasak ta, sre hatrlar. a u u c Biz sadece hatalar sisteme girmeyi hatrlamalyz (Kural #3, #4). O zaman bu blmde anlatlacak teknikleri u balklar altnda toplayabilou s s iriz: Karakterler Proje yneticileri o Teknik liderler 332

Karakterler Programclar Gelitirme Sreleri s u c Hata takip Kaynak kod idaresi Kod teftii (code review) s Gelitirme ve test s Planlama yntemi o

11.1

Karakterler

Bir yazlm takmnda doldurulmas gereken eitli roller vardr; Bu roller, bizim c s imdiye kadar grdumz kurumsal yazlm takmlar ve danman (consults o ug u s ing) irketleri baz alnarak anlatlacaktr. Her rol iin ayr bir ahsn bulunmas s c s en optimal ozmdr, fakat bzen bir ve ya daha fazla rol ayn kii uzerinde c u u a s de olabilir. Bu karar takmn ve projenin byklune gre verilebilir. Fakat u u ug o danman irketleri her zaman bir rol, bir kiiye verirler. s s u s

11.1.1

Proje Yneticisi o

Bir yazlm projesinde teknik olmas gerekmeyen nadir kiilerden biri, proje s yneticisidir (project manager). Fakat genellikle, proje yneticilerinin programclk o o gemii vardr, sadece, bu yaptklar i iin zorunlu deildir. Hi teknik olmayan, c s s c g c fakat ok iyi proje yneticileri ile ahsen altmz syleyebiliriz. c o s c s g o Proje yneticisinin yapt iler, yazlm projenizin hangi safhasnda olduunuza o g s g gre deiir, fakat genel olarak denebilir ki proje yneticisi takmnza lojistik o gs o destek salamakla ykmldr. Tandm bir teknik lider proje yneticileri g u u u u g o hakknda unu sylerdi: Programclar kara kuvvetleri ise, proje yneticileri s o o hava kuvvetleridir. Biz yerden taarruz ederken, onlar havadan destei salar. g g Bu ok doru bir gzlemdir. Hakikaten de proje yneticilerinin en iyisi, takm c g o o bir sorun blgesine gelmeden, o sorunu nceden tahmin edip, o konu hakknda o o nlem alabilendir (sorunun tasarm ile ilgisi olmamaldr). Tandm en iyi o g yneticilerden biri olan Arpan Sheth, bu becerinin ok gzel bir rneini bir o c u o g projemizde gstermiti. o s Arpan ile beraber altmz bu projede teknik takm, projenin urn seme c s g u c ve teknik bilgi toplama aamasndayd. Fakat, daha o safhaya gelmemi olsak s s bile, gelitirmeye balamak iin gerekli Sun Solaris makinalarmz hla ortas s c a larda yoktu. Gelitirmeyi o makinalar uzerinde yapmamz gerekiyordu, ve o s aamaya gelmemi olsak bile, o aamaya geldiimizde yere dtumz anda s s s g us ug u komaya balamamz (hit the ground running) iin, makinalarn bir an nce s s c o gelmesi ok nemliydi. c o 333

11. PROJE YONETIMI Ve proje yneticimiz Arpan, geciken makinalarn problem olabileceini ayo g larca nceden tahmin etmiti. Kendisi hemen gerekli yerlerde dmelere baso s ug maya balam, ve geriye mterimizden makinalar iin mteriden paray als s us c us mak kalmt. Son ve en kt prz ite burada ortaya kt; Bir btelendirme s ou uu s c uc problemi yznden mteri demeyi istediimiz kadar hzl yapamayacakt. Bu u u us o g durum makinalarn alnmasn aylarca geciktirebilirdi! Bunun uzerine Arpan yle yaratc bir zm buldu: Makinalar bizim danman irketimize aldrp, so co u s s mteriye bu makinalar lease ediyormu gibi bedelini yava yava detecektik. us s s so Mteri bu deme ekline ikna oldu, ve gelitirme takmmz urn seimi ve us o s s u c testleri bitirdiinde, makinalar bizi hazr bir hlde bekliyordu. Htta Arpann g a a ayarlad lease demeleri, faizi hesaba katlsa bile, irketimiz iin ufak bir kr g o s c a elde edecekti! s Ite iyi hava destei budur. Kara kuvvetleri gelmeden hedef belirlenip yklm, g s ve geriye sadece karadan yaplabilecek hamleleri yapmak kalmtr. Proje ynetis o cisi tabii ki atlayp kod yazmaya balayamaz, ya da tasarm yapamaz, fakat s projeye gereken tm kaynaklarn mevcut olmas iin gerekli her eyi yapar. Bu u c s rnekten renilmesi gereken dier bir davran, baarl bir proje yneticisinin o og g s s o en yksek risk noktalarna nasl hemen odaklandn grmektir. Gelitirme u g o s makinelerin ortada olmamas, bir gelitirme takm iin en yksek risk tayan s c u s durumlardan biridir (alternatif iletim sistemlerinde gelitirmemiz szkonusu s s o deildi) ve ynetici bu durumu kavram ve iin peini brakmayarak tm dikkag o s s s u tini ve enerjisini oraya ynelterek ii sonucunu vardrmtr. o s s Gereklilik Listesi Gereklilik listesi, yni mterinin yazlm takmndan bekledii ilevler, proje a us g s yneticisinin takip etmesi gereken ilerden biridir. Bu listenin ne olaca hakknda o s g tartmalarda proje lideri ba rol teknik lider ile paylar, unk gereklilik liss s u s c u tesinde olanlar programclarn ne kodlayacan ilgilendirir, ve programclarn g ne kodlayaca projenin ne zaman biteceini ilgilendirir. Proje biti tarihine g g s tam zamannda ve en az hata ile ulamak proje yneticisinin en nemli hedes o o dir. Bu sebeple gereklilik listesi kelimelerinin duyduu anda, proje yneticisi g o kulak kabartmaldr. Proje yneticisi gereklilik listesi hakknda srekli teknik lider ile istiare o u s durumunda olur. Ynetici hibir zaman tek bana bir gerekliliin ne kadar o c s g srecei hakknda bir karar, teknik lider olmadan, vermemelidir. Bu karar en u g iyi verebilecek kii teknik dnyann iinde gelen teknik liderdir. s u c Sabit zamanl, sabit yatl projelerde, uzerinde kaynak (deiik yetenek gs lerdeki programclardan ka tane olduu) ve yat pazarlklarnn yaplabilecei c g g bir plan dkmannn hazrlanmas gerekir. Bu belgenin yazlmas genellikle o u danman irketlerinde her programcya blm blm datlr. Bu belgenin s s ou ou g blmlerinin datlmas, hangi iin kimde olduunun takip edilmesi, sonra ou g s g blmlerin herkesten alnp birletirilmesi ve gerekirse bir teknik yazara verou s ilmesi proje yneticisinin sorumluluudur. Plan belgesindeki teknik altyap, o g 334

Karakterler ve mimari ksm teknik lider tarafndan yrtlecektir. Teknik altyapnn niye uuu plan belgesinde gereklilikler ile beraber olduunu anlamak iin 11.2 blmne g c ou u bakabilirsiniz. Hata Takip Proje, kodlama safhasnda ilerleyip sra kullanc testleri baladktan sonra, s proje yneticisi yeni bir rol ustlenerek sper testi hline dnur. Onyzn o u c a o us u u kullanmn en iyi bilen kii o olmaldr, ve plan belgesinde olan hereyin kods s lanm olup olmadn bir yandan kontrol etmelidir. Tm zelliklerin kods g u o lanm olmasndan ynetici, en az teknik lider kadar sorumludur, fakat derin s o teknik bir alanda taklp kalabilmesi mmkn olan teknik lidere nazaran proje u u yneticinin nyze dnk kontrolleri yapmas iin daha ok frsat vardr. Bu o o u o u c c yzden bu grevde barol ynetici almaldr. u o s u o Testiler uygulamay test edip hata bulduka, bunlar hata takip sistemc c ine girerler (11.3.5). Hata takip sistemindeki hatalarn ne kadar hzl tamir edildii, hangi hatalarn srekli gidip geldii, ya da bazlarnn neden uzun g u g sre tamir edilemedii gibi konular proje yneticisi bilir durumda olmaldr. u g o Onem seviyesi, aciliyeti (priority) yksek olan hatalar tamir eden programclar u ile ynetici, direk istiare hlinde olabilir. Proje yneticisi, nemli hatalar o s a o o hakknda ilgili programclara hatrlatmada bulunabilir, ve iin nemini ons o lara hissettirecek ekilde onlarla konuabilir. Eer ilgili programclar moral s s g duklu yayorlar ise, belki bunun hakknda bir eyler yaplmas gerekiyus ug s s ordur. Hatalarn tamiri iin teknik destek tabii ki teknik liderden gelmelidir, c fakat proje yneticisi hatrlatc ve kontrol edici, ve gerekirse kaynak salayc o g bir durumda hep hazr olmaldr. Tandmz proje yneticileri, nemli, ve testiden programcya fazlaca g o o c gidip gelen, hata nolar ezbere bilirlerdi. Bu yneticilerin mesel No 334 ne o a durumda? gibi sorular sorduklarn duyardnz. Bu tavrlar, projede ilerin s tamamen kontrolleri altnda olduu izlenimini verirdi (ve hakikaten yleydi), ve g o bu da programclarn daha dikkatli olmasn salard. Psikolojik olarak birinin g yaptnz ile ilgileniyor olmas, o ite daha iyi performans gstermenizi salar. g s s o g Cunk hata tamir edildiinde, hata 334 ne durumda? sorusuna tamir edildi u g cevab verilebilecektir. Programc yararllk gstermitir ve ilgilendii konuda o s g bunu direk yneticiye syleyebilmitir. o o s Sosyal Konular Projenin sosyal atardamar proje yneticisidir. Ge vakte kadar almalar o c c s tavsiye etmesek bile, eer bu almalar olursa alsmadan sonra dlleri (restoran, g c s c o u bar) datan kii, proje yneticisi olmaldr. Programclar gen bir grup ise, g s o c bir i gnnden sonra bara, yemee gtrlmelerini dzenleyecek kii proje s u u g ouu u s yneticisi olmaldr. o 335

11. PROJE YONETIMI Ynetici her programc ile iyi bir iletiimde bulunmaldr. Onlar tanmal, o s ve zel hayatlar hakknda ok derinliine olmasa bile kir sahibi olacak kadar o c g bir yaknlkta olmaldr. Hi unutmamak gerekir ki insanlar sevdikleri ve saydklar c yneticiler iin daha ok alrlar. Bu tekniin tersi, mthi bir dikta ile koo c c c s g u s rku kullanarak ynetmektir, fakat korkunun sevgi/sayg kadar motive edici olo mayacan rahatlkla syleyebiliriz. Hibir insann, korku kullanarak, o ekstra g o c kilometreyi komasn salayamayz. s g Belli bir alanda uzmanl olan her grup kendine has alkanlklar, konuma g s s stili ve bir alt kltr uretir. Bu kltr tanmak proje yneticisi iin faydal u u u uu o c olacaktr. Mesel benim iinde olduum kurumsal danman olan bizler Unixi a c g s sayar Microsoftu sevmeyiz. Oce Space lmine gleriz. Resmi giyinmek bizim u iin en byk cezalardan biridir. Sk almak problem deildir, ama sk da c u u c s g elenilmelidir. Bu tr kltrel anektodlardan haberdar olmak proje idarecisini g u u u daha etkili yapar.

11.1.2

Teknik Lider

Projenin olmazsa olmayan kiilii, her eyin etrafnda dndu, her kararn s g s o ug paras olmas gereken ahs teknik liderdir. Projenin teknik sorumluluu tamac s g men teknik liderin uzerindedir. Ondan baka sorumlu aranmaz. s Bu sebeple teknik lider (ksaca TL diyelim), projenin mimarisi ve kullanaca teknolojileri semek ile sorumludur. Bir projede teknik liderin kabul g c etmedii hibir teknoloji kullanlamaz. Programclar tavsiyeler getirebilirler ve g c bunlar ounlukla mimariyi pek ilgilendirmeyecek ufak, izole alanlar iin olac g c caktr, fakat gnn sonunda teknoloji seimi, mimariyi etkilesin ya da etku u c ilemesin, tamamen teknik lidere ait olan bir karardr. TL bu konuda karar verdiinde, kararn aynen uygulanmas gerekir. g Bu konuyu yle aklayalm: Sorumluluk ile yetkinin ayn kiide olmas so c s gerektii aktr. Eer sorumluluk var fakat yetki yoksa, bu durum teknik liderin g c g uzerinde kontrol dndaki bir durumun sorumluluunu alma stresi getirirdi ki u s g bu hibir teknik lider kabul etmeyecektir. Bu yzden bizim altmz hibir c u c s g c irkette TLin izni dnda teknoloji kullanlmasna izin verilmez. Programclar s s seviyesinde teknolojiler hakknda bir heyecan ve bunu da kullanalm sa g mevcuttur, ve bu san yerine pragmatizme brakmas sadece ve sadece teknik g lider seviyesine eriildiinde kristalleir. Bu yzden bu karar daha tecrbeli s g s u u olan teknik lidere braklr. Kurumsal uygulamalarda teknolojinin pr nesnesel u tasarmdan bile nemli olduunu sylemitik, unk yanl yaplan bir teknoloji o g o s c u s seimi, programcnza ve projenize kayp zaman, kalitesiz ve kt performansl c ou kod anlamna gelir, ve bu sebeple bu sorumluluu teknik liderden bakas alg s mamaldr. Ayrca teknik sorunlar knca yardm etmesi beklenen teknik lider c olduu iin, kendi yardm edemeyecei bir teknolojinin kullanlmasn hibir g c g c teknik lider istemez. Teknolojilere karar verdikten sonra, TL kullanmasn planland yeni teknolog s jileri testten geirip kontrol etmeye balayabilir. Ilerlik kontrol (proof of conc s u 336

Karakterler cept) balamnda TL, kullanaca teknolojiyi kontrol etmek iin alan ufak g g c c s rnekler yazabilir. Teknik lider, teknoloji ile kendini rahat hissedinceye kadar o bu denemeleri yapacaktr. Teknik lider, gerek kodlama asndan, sadece mimariden ve (az miktarda c c kod ieren) gelitirme, ve deployment scriptlerinden sorumlu olacaktr. Teknik c s liderin ok fazla gereklilik kodlamas beklenmemelidir. Cunk teknik lider, her c u yere yetiebilen ve yangnlar kt yerde sndrebilen bir durumda olmaldr, s c g o u ama eer kendisi ok fazla kod yazyorsa, o zaman dier nemli sorumluluklarn g c g o yerine getirmesi zorlar. Danmanlk azyla sylemek gerekirse, teknik lider s s g o kendini kritik gei noktasna koymamaldr1 . cs Mimari Mimari tasarm, gereklilik listesinin hazrland srada paralelde yaplr, ve g bittikten sonra gerekliliklerle beraber plan belgesinin bir blmnde anlatlarak ou u mteriye sunulur. Mimari belgelendikten sonra TL, kaynak kod idare sistemini us kurar, ardndan planlad mimariyi ilk nce kendisi kullanarak bir rnek zellik g o o o kodlar. Bylece ayn mimariyi kullanacak olan programclarn nne bir rnek o o u o koymu olur, ayn zamanda mimariyi hem kendisine hem de dier programclara s g ispat eder. Ak sylemek gerekirse bir projede teknik liderin en nemli grevi, proc o o o gramclar seri uretim aamasna getirmektir. Seri uretimden kastmz, her s gereklilik iin yazlmas gereken kodlarn kullanaca altyap kodlarnn ve kuc g rallarn hazr olup, programcnn sadece ve sadece gereklilik iin kod yazac cak duruma gelmi olmasdr. Seri uretime hazr bir takm ve programc u s s u nasl yaplacak eklinde sorular daha az sorar, unk artk bir yazd s s c u g gereklilik kodu bir nceki gereklilie benzer hldedir, ve kurallar bile oradan o g a alarak sadece ilem mantna odaklanabilir. Seri uretim, teknoloji kullanmnn s g tm hatlarnn ortaya konulmu olmas demektir. Teknoloji kullanm, mimari u s demektir. Mimarinin tam tanm iin 8.4 blmne bakabilirsiniz. c ou u Seri uretim sahfasna gelmi olan bir takma, ne kadar fazla programc ek s lerseniz, o kadar fazla i alrsnz. Bu adan baklacak olursa Frederick Brooksun s c syledii ge kalm bir projeye daha fazla programc eklemek o projeyi daha o g c s geciktirir[11, sf. 25] sz yanltr. Yanl mimari, gereklilik kodlamasn geciko u s s tirebilir, fakat optimal bir mimari ile daha fazla programc daha fazla i demeks tir. Gelitirme S releri s u c Gelitirme sreleri, kaynak kod idare sistemini nasl kullanlaca, hangi alt s u c g dizin yaplarnn kullanlmas gerektii, ve programclarn kendi testlerini nasl g iletecei gibi konular kapsar, ve en az mimari kadar nemlidir. s g o
1 Technical

lead must not be in the critical path

337

11. PROJE YONETIMI Kaynak kod idare (KKI) sistemi CVS gibi bir urn olabilir, bu urn uzerinde u u tm proje kodlarnn tutulaca bir depoyu yaratmak teknik liderin sorumu g luluundadr. Depoyu yaratma iini mimariyi ve ilk gereklilii kodlarken yag s g pabilir. Eer depo yarama grevini TL baka birine devretmek isterse, bunu g o s KKI sisteminin nasl kurulacan bilmedii iin deil, yeni bir kiiye bu bilgiyi g g c g s transfer etmek iin yapmaldr. Yni her artta teknik lider KKI sistemlerinin c a s detaylarn ok iyi bilmelidir. c Hata takip dzeni projenin balarnda kurulmas mecbur deildir. Bu sisu s g tem, testiler kurumsal uygulamay ciddi kullanmaya balayncaya kadar ok c s c gerekli olmaz, fakat o zaman gelince hata takip sistemi teknik lider tarafndan hazr edilmi olmaldr. Hatt irketimizin her projesi iin ortak kulland (ama s as c g hata verilerinin her proje iin ayr tutulduu) bir hata takip programnn olc g mas faydal olur. Ortak KKI program da ayn ekilde iyi bir kirdir, tabii s doal olarak depo yaratma ilemi teknik KKI bilgisi gerektirecektir. g s Gelitirme ortamyla ilgili ek baz davran kurallar yeri geldike teknik s s c lider tarafndan koyulabilir. Mesel yaygn bir ak kaynak prensibi olan her a c kod ekleme (check in) sonras proje gelitirici listesine eklenen kod ile ilgili bir s mesaj gnderme kuraln teknik lider koyup (htta koymaldr) takip edilmesini o a salayabilir. g Kod Kalitesi Teknik lider, projedeki kodun kalitesinden sorumlu kiidir. Bu amala belli s c aralklarla kod tefti toplantlar yaplmas yararldr. Bu toplantlardan nce s o TL, hangi kodlarn tefti edileceini belirler. Bu toplantlar detayl olarak 11.3.3 s g blmnde anlatlacaktr. ou u TL organize, gurup hlinde teftiler yapt gibi bazen raslantsal ve nokta a s g saldrs yaparak kodun belli blgelerine bakarak kontrol yapabilir. Bu raslantsal o kontrollerden sonra eer houna gitmeyen bir nokta bulursa, programcya bu g s yorumu bir tavsiye olarak gtrebilir. ou Kod kalitesi iin nemli bir husus olan birim testlerinin kullanlmaya tevik c o s edilmesini teknik lider ustlenmelidir. Eer otomize edilmi kabul testleri var g s ise, bu testlerin yazlmas iin bir kaynak (kii) ayrlmas teknik lider proje c s yneticisi ile birlikte gtrr. Kabul testleri iin kullanlacak program (7.2) o ouu c TL ok detayl bir ekilde bilmelidir. Bu programn kullanlmas iin tm soruc s c u lar ilk bata ona gelecektir. Bu program teknik olarak kavrandktan sonra, proje s yneticisi tm gereken kabul testlerinin yazlma ilemini testleri yazmakla soo u s rumlu kiiyle beraber teknik liderden bamsz bir ekilde gtrebilir. s g s ou Sosyal Konular Programclar ve teknik lider arasndaki iletiimin ana hatlar unlardr: Pros s gramc, mimariye ve teknik liderin proje bazndaki koyduu dier genel kug g rallara uymaya mecburdur, ama bunun haricinde teknik lider ile programcs 338

Karakterler g arasnda bir renci/retmen ilikisi olacaktr. Orenci/retmen ilikisinde og og s og s retmen, yani teknik lider, zorlayc olmamaldr. Programc ona bir soru sorup og bir teknik konu hakknda yn beklediinde ona cevab muhakkak verecektir, o g fakat eer performans sonular ok fark etmiyorsa teknik lider programcya g c c nal, unu yap havasnda bir yn vermekten kanmaldr. s o c Eer teknik lider, ok performans fark getirmeyecek ama daha temiz bir g c yntem bulmusa bunu programcsna u yaklam hi dundn m diyo s s s c us u u erek getirmeli ama srarc olmamaldr. Doru yolu programc isterse semeli, g c istemezse kendi yolundan devam etmelidir. Mimariye bal kalmak ok nemg c o lidir, teknik lider mimariden feragat etmemelidir; Bahsettiimiz bo alan, g s mimariyle gerekliliin arasnda kalan bo alandr. g s Programclar bazen, ok etrel bir duruma saplandlarnda kendilerine c c gveni kaybedebilirler. Bu gibi ruhani (!) konular bizim gibi teknik konular u tercih eden insanlar iin en zor konular oluyor. Fakat bu gibi durumlar ok c c iyi idare etmemiz gerekmektedir, unk takmmzn motivasyonu bu idaremc u ize bal olacaktr. Eer programc kendinden uphe eden bir yaklamla lidere g g s s geliyor, ama teknik bir soruyu direk sormuyorsa, bunun tek anlam vardr: Morale ihtiyac vardr. Bir problemi zmekte uzun zaman alarak takmn co gznden mi dmektedir? Durumu iyi analiz ederek, bu soruna tek ekilde o u us s yaklaabilirsiniz; Eer programc star programclarmzdan biriyse, ona kendine s g gven alamalyz. Bu noktada yapabileceimiz en kt ey, i yapsn sadece u s g ous c o programcnn bilecei duruma atlayp programcy bir kenara iterek, problemi g direk zmeye uramaktr. Cunk 1) bunu yapamayabiliriz 2) programcmza, co g s u ona gvenmediimiz sinyalini gndermi olarak motivasyonunu baltalam oluu g o s s ruz. Motivasyon faktrn genel takm baznda da takip etmemiz ve maniple ou u u etmemiz gerekmektedir. Takm baznda yaptmz burada bir sorun var, g hadi arkadalar ve ite baardk szlerinin takmnz uzerinde ne kadar etks s s o ili olduunu hi unutmamalyz. Bu szler ve davranlarla, takmn ritmi tamag c o s men teknik liderin elindedir. Cok uzun sreli iler iyi gitmiyor modu takm u s motivasyonu iin faydal deildir, bu dnemi muhakkak bir ite baardk c g o s s zaferi izlemelidir. Bu zafer programclara belli edilmeli ve abalarnn sonuca c eritii ortaya kmaldr. Zafer noktasna erimek iin eer teknik lider kollarn s g c s c g svayarak programc ile birebir oturmas anlamna geliyorsa, bu yaplmaldr. Unutmayalm ki, zellikle balang seviyesi programclar, zaten renmek o s c og iin oradadrlar ve zmnz anlayp renmi olmaktan, ve bir sonraki sec co u u u u og s ferde kullanabilecek durumda olmaktan mutlu olacaklardr. Baar noktasna s eritiinizde bylece onlarn da motivasyonu artar. s g o Byk tepe noktalarn byk kutlama izlemelidir, kutlamalar organize u u u u etmek proje yneticisinin grevidir, fakat takm o noktaya getirmek (ok daha o o c zor) teknik liderin sorumluluudur. g 339

11. PROJE YONETIMI

11.1.3

Programclar

Programclar bir takmn iini ureten, onu ileri iten pistondurlar. Mimariyi s hazrlamak ve programclarn nlerindeki tekniksel ve kaynaksal barikatlar o ykmak her ne kadar teknik liderin ve proje yneticisinin grevi olsa da, bu eno o gellerden sonra nihai ii yapacak olan kiiler, programclardan bakas deildir. s s s g Bir programnn sahip olduu en nemli zelliklerden biri, sebat etmektir g o o (persistence). Program yazarken problemler, teknoloji bazl olsun olmasn her zaman ortaya karlar, ve bu olduu zaman programc ylmayan, problemin c g uzerine tekrar tekrar giden, ve bzen deiik alardan yaklamay deneyerek a gs c s sonuca varabilen trden bir insan olmaldr. u Programcnn yeni teknolojileri rahat renebilmesi onun esnekliini ve seeneklerini og g c arttrc faktrlerden birisidir. Kurumsal programclkta ve zellikle kurumsal o o programclk yapan danmanlk irketlerinde, her projede yeni bir teknoloji s s kullanlmas kanlmazdr, bu sebeple yeni teknolojileri anlayabilme ve kullanc abilme programc iin vazgeilmez bir yetenek hline gelir. c c a Aranan bir dier zellik, enerjidir. Amerikada birok mstakbel programcnn g o c u mlakatn yaparken baktmz ana parametrelerden biri hep bu oluyordu. u g Enerjiyi anlamak iin programcnn nasl davrandna, teknoloji hakkndaki c g heyecanna ve problemlere yaklarken ki tutumuna bakabiliriz. s Programclar her projede genellikle acemi (junior) ve usta (senior) seviyesinde iki kategoriye ayrabiliriz; Bu kategoriler programclarn alt irket c s g s iinde HR (Insan Kaynaklar) tarafndan verilmi ve periyodik olarak bir sonc s raki seviyeye gei (ykselme) kriterleri iin kontrol edilen payeler olabilirler. cs u c Bu durumda junior ya da senior olmann maasal etkileri olacaktr. Bu iin HR s s tarafdr, biz teknik olarak bu kelimelerin anlamyla ilgileneceiz. g Junior Programclar Junior, Ingilizce giri seviyesi ya da acemi anlamna gelir. Bir programc ilk s projesinde, ve ilk iinde bu seviyede olacaktr. Junior bir programcnn, pros jede kullanlan bilgisayar dilini ve veri taban kavramlarn bilmesi beklenir, ama geri kalan ou teknolojiyi bilmiyor olabilir. Ayrca tasarm dzenleri, mic g u marileri takip etmek konusunda yardma ihtiyac olacaktr. Junior programc teknolojileri kendi bana renirken zorluk ekebilir. Fakat enerjik ve akll bir s og c programcysa, yol gsterilince istenilen yere rahatlkla gidebilen bir kiidir, ve o s teknik liderden ya da senior programclardan yardm alnca kendi iini halledes cek duruma gelir. Junior programclar teknolojiyi renirken, bir yandan renmeyi renirler. og og og Bir teknolojinin pf noktalarn kapan bir junior progamc tipik olarak yeni u teknolojileri daha rahat anlamaya balar. Bu ekilde ilerleyerek senior dzeyine s s u kma yolunda admlar atm olacaktr. c s Projemizde bir mimarinin olmas, en ok junior programclar iin yararldr, c c unk mimarinin yol gsterici zellii onlar iin iyi bir rehber hline gelir. c u o o g c a 340

Karakterler Yaygn yaplan hatalara kar kurallar iyi oluturulmu bir mimari, junior s s s programcy tuzaklardan koruyacak, ve sadece ilem mant koduna odaklans g masna izin verecektir. Ayrca mimariye bakarak ve onunla ilgili sorulara sorarak, teknik liderin teknoloji ve yazlm gelitirme felsefesi hakkndaki bilgisini s alm olur. s Junior programc, renmek iin orda olsa da, gnn sonunda i yapmas og c u u s beklenir, ve ona harcanandan daha fazla zaman, yaplm i olarak geri vers s melidir. Eer ok fazla soru soruyorsa ve i yaparken harcad zaman, ona g c s g retilmekte harcanan zamandan daha fazla ise, bu bir eksikliktir, ve programc og uyarlmaldr. Senior Programc Senior programc yeni teknolojiyi renme, ve bir problemi zme konusunda en og co becerikli programcdr. Senior programcnn en iyi tanm, dardan sfr (ya s da ok az) yardmla, bir problem beini kendi bana zen programc cmlec o g s co u sidir. Teknik liderden bir ta aa olan bu programcnn teknik liderden farkc s g lar, mimari hazrlamak, Unix ve byk sistemlerde uygulamarn almasn u u c s anlamak, performans optimizasyonu, gelitirme ortam hazrlama, planlama, ve s sadece tecrbeyle alnabilecek ok ince teknolojik detaylar konularnda olabilir. u c Bunun haricinde senior programc, teknoloji semek, kulanmak, tasarm yapc mak ve nesnesel modellemede olduka ileri bir durumdadr. Kendine verilmi c s bek iindeki kodun kalitesini uzerine alabilir, birim test tekniklerinden habo c erdardr. Hibir teknolojinin kuruluu ve kullanm onun iin problem deildir, c s c g en yeni teknolojiyi alp iler hle getirebilir. Bu teknolojiyi kullanarak en temiz s a mimariyi kuramayacak olabilir, fakat altrmada problem ekmez. c s c Senior programc mimari takip etmekte iyidir, ve mimaride baz boluklar s kefederse bunlar teknik lidere sylemelidir. Sonuta senior programcnn bir s o c sonraki kariyer basama teknik liderlik olacaktr, bu yolda giderken kendine g gereken ek yetenekleri liderden almaya uramaldr. Teknik mimarinin tasarm g s seimlerini anlamak bu ek yeteneklerden biridir. c Teknik liderlik yolunda senior programcya yardmc olmak iin takmdaki c teknik lider, gelecek vaadeden senior programcya kendi grevlerinden bazlarn o ykleyebilir. Mesel plan dokmanndaki mimarinin belgelenmesi senior prou a u gramcya aktarlabilir, ya da gelitirme ortamnn kurulmas (CVS), ya da s hazrlanm mimariyi kullanan ilk gerekliliin kodlanmas senior programcya s g verilmi bir grev olabilir. s o Junior programclar takldklar yerler hakknda soru sormak iin senior c bir kiiye gelebilirler. Bu sorular, projenin mimarisi, karlalan bir problem s s s ya da hata bulmak (troubleshooting) konularnda olabilir, senior programc kendi ileri geriye dmedii srece bu sorulara cevap verebilir. Ama esas s us g u yangn sndrc teknik liderdir, belli bir sre harcandktan sonra problem o uu u u hal zlmediyse teknik lider konuya dahil olmaldr, unk ustne en az a co u c u u kodlama sorumluluunu alm olan teknik liderdir (mimari kodlama projenin g s 341

11. PROJE YONETIMI banda yaplm ve bitmitir) bu yzden yardm etmek iin en fazla zaman s s s u c olan tek kii o olacaktr. s

11.2

Planlama

Bir ie balamadan nce plan yapmann nemini general ve eski ABD Bakan s s o o s olan Eisenhower ok gzel tarif eder: Bir sava srasnda planlarn genellikle c u s ie yaramadn grdm, ama yine de planlamak, bir sava iin en vazgeilmez s g o u s c c eylemdir[13]. Insanolunun evrimi srasnda srekli olarak bilgi ileyebilme kag u s pasitesi artmtr[12, sf. 138] ve bilgi ileme, onu kaydetme, bilgiden renmek s s og anlamna geldiine gre, bu yeni kapasite renim, tecrbe ve ngr olarak g o og u o ou insana ileriyi tahmin yeteneini arttrmasn salamtr. Bu art, planlarmzn g g s s daha doru olaca anlamna gelmi ve direk sonu olarak hayatta kalma ansmz g g s c s arttrmtr. s Planlar, tecrbeden destek alan doru ngrler uzerine kurulursa ok baarl u g o ou c s olurlar. Fakat dzgn ngrler uzerine kurulmamlar bile olsalar, planlar u u o ou s baarsz olacaklar ana kadar bir gidi yn salarlar, ve ilememeye baladklar s s o u g s s anda plan ile gerek durumun farkn iyice belirgenletirecekleri iin, Eisenc s c howern dedii gibi, ortada olmalar vazgeilmez kaynaklar hlini alrlar. g c a %100 ngr, engin teknik ve ynetim tecrbesi gerektirir, ve bu tecrbeyi o ou o u u bu kitaptaki deiik blmlerde aktarmaya altk. Geriye tek bir konu kald: gs ou c s Planlama plann, yni bir planlama srecinin takip edecei baz faydal kua u g rallar vermemiz gerekiyor. Bylece planlayclar uzerinde hatrlatc noktao lar yaratarak, planlamada yaplabilecek mekanik hatalar en aza indirgemeyi amalyoruz, ayrca, bu plandan kmas gereken belgeleri ortaya koyarak, proc c fosyonel bir yazlm projesinin mterisi ile arasnda nemli olan iletiim nokus o s talarn gstermeyi amalyoruz. o c Planlamann ka ay ileriye doru yaplmas gerektii, uzerinde olduka dunlm c g g c us u us ve tartma yaplm dier bir konudur; Bu konu hakknda sektrn seimini s s g ou c sunmaya alacaz. c s g

11.2.1

Ne Kadar Ileri Grelim? o

Bu sorunun mterimiz (i sahibi, projeyi sipar vermek isteyen kii) asndan, us s s s c ve yazlm ekibi iin ayr ayr cevaplanmas gereken iki baca vardr. Yazlm c g ekibi iin bu cevap grebileceimiz kadar ileriye olmal, mteri iin ise, en c o g us c ok kr getirmesi mmkn olan an az yazlma yetecek kadar olmaldr. Bu c a u u iki nokta arasnda hangi tarafn daha ar basacan yazlm takmnn istedii g g g yat belirleyecektir. Fiyat, (projedeki eleman kalitesi ve bunlarn saylar) x (kalite birim yat) x (projede harcanan gn) denkleminden kacaktr. Eer u c g mteri krn mmkn olduu kadar arttrp tam zellikli bir yazlm istiyorsa us a u u g o ve bunun bedelini demeye hazrsa, yazlm takm grebilecei kadar ileriye o o g giden bir proje kapsamn mteriye hazrlayp sunmakta serbesttir. us 342

Planlama Yazlm takm niye grebilecei kadar ileriyi grmeye uramaldr? Buna o g o g s kar bir soruyla cevap verelim: Eer bunu yapabiliyorsak, niye yapmayalm? s g Bir ii daha iyi yapmas beklenen bir yazlm, kendi iinde bir btndr ve sons c uu u radan bamza dert olabilecek durumlar ngrebiliyorsak, bu btn iinde olas o o uu c bilecekleri ngrebilmemiz gerekir, htta ngrmeliyiz. Cunk yazlmn kalitesi o o a o o u ve kodun sonradan deimesini engellemek bunun faydas olacaktr. gs Baz planlama srelerine gre, uza grebiliyorsak bile, grmemek daha u c o g o o iyidir, unk o zamana kadar mterinin kri de, etraftaki baka artlarda c u us s s deimi olacaktr. Onlara gre zten tasarm dzgn yapmamz mmkn gs s o a u u u u deildir. Ayrca mteriye ne yapacan sylememeliyiz, unk o iini en iyi g us g o c u s bilendir. Bu duncelere katlmyoruz, unk cevap vermeye sonran balamak gerekirse, us c u s danmanlk dnyasnn nemli bir kanununu yle der: Mteri ne istediini s u o so us g bilmez. Yni, bir projenin banda en parlak, renkli, acaip nyz ve veri yaps a s o u tasarmlarn gerektiren gereklilikleri nnze getiren mteri olacaktr, fakat o u u us teknolojiyi, htta bzen kendi i yaplarn ve o yapnn ne olmas gerektiini a a s g ounlukla anlamadklar iin, gereki seimler yapamazlar. O zaman, bir c g c c c c danman mteriye ileriye dnk, srekli deimesi gerekmeyecek (salam) bir s us o u u gs g i sreci dahilinde bir IT sistemini tavsiye edecek durumdaki en uygun kiidir. s u s Mteriniz, bu tavsiyeyi alnca mutlu da olacaktr. us Tasarm dzgn yapamama, sadece kullanmas gereken teknolojileri iyi u u bilmeyen takmlar ve teknik liderler iin geerlidir, bu yzden pire iin yorgan c c u c yaklmamas en iyi seimdir. Teknik mimar zten uzerinden optimal bir mic a mari kuramayaca bir ie kalkmamaldr, bunun tersi intihardr. Teknik lider g s s byle bir ie giriirse, projenin biti tarihini tehlikeye atm olur, ama bu sebeo s s s s ple her teknik lideri bilgi seviyesi ne olursa olsun mimari tasarlamaktan men etmek, %99 artlarda kaliteye sebebiyet verebilecek planlama aamasndan bizi s s mahrum brakmek anlamna gelecektir. Eer teknolojiyi anlamayan teknik lider g ve ona bu grevi vermekte saknca grmeyen danman irketinin en yksek o o s s u teknik grevlisi (CTO) iine girdikleri riskin farknda deillerse, aldklar risk o c g geri tepecektir, ve tepmelidir; Tahmin edilen sonu, daralp iten kan proc s c gramclar, mteriye zamannda yazlm verememekten lekelenen bir un ve us kayp i ve zaman olacaktr. Ksacas piyasa kanunlar durumu hlledecektir. s a Mterinin krinin deime argmann herhalde (ayn anda cevaplam) us gs u s olduk, unk mteriye, deimeyecek kirleri gstermek projenizin planlama c u us gs o takmnn grevidir. Mteri tabii ki planlama dkman imzalandktan sonra o us o u ok gerekli deiimleri yapabilmelidir, ama bunun cevab ayr bir sipari deiim c gs s gs belgesi (change order document) ve srecidir. Bu deiim bir mini planlama u gs evresinden geer, ve sonucunda ayr yatlandrmas gereken bir belgeye sebec biyet verecektir. Konjektrden kaynaklanan deiimler hakknda ise yapacak bir ey zaten u gs s yoktur. Eer srf bunun iin rzgar her deitiinde baka yne gidebilen bir g c u gs g s o planlama sreci kullanrsak, o zaman habire projeye yeniden balam oluyoruz u s s demektir, ve bu, uzun vadeli planlamadan elimize geecek hibir kazanmdan c c 343

11. PROJE YONETIMI istifade edemiyoruz demektir. Burada esas sorulmas gereken, eer konjektr g u deimi ise, niye belli bir ynde gidecek bir yazlmn ve i stratejisinin daha gs s o s batan ele alnm olduudur. Bir yerde bir hata yaplmtr, ve bu hata yazlm s s g s projesinin ok uzerinde, stratejik balamda yaplmtr. Eer bu hata yaplmsa, c g s g s o ana kadar yazlm kod atmaktan baka are yoktur. Bu kod kullanlabildii s s c g kadaryla yeni proje ynnde kullanlmaya uralabilir. Ama undan emin olo u g s s mamz gerekiyor ki, konjektr ok fazla deimi ve bu i plan uzerinde ok u c gs s s c byk deiikliklere sebebiyet verdiyse, ustnde alacamz ey yeni bir prou u gs u c s g s jedir. Bu, gereklilik toplama, mimariyi tasarlama, vs. gibi tm basamaklarn u silbatan tekrarlanmas anlamna gelir. s

11.2.2

UGB

Kitabmzda, bir yazlmn planlama oda olarak tek bir dkman nereceiz: g o u o g Uygulama Gelitirme Belgesi (UGB). Bu belgenin isminin gereklilik belgesi s olmamasnn sebebi, iinde gerekliliklerin listesine ek olarak teknik mimarinin c de ilenecek olmasdr. UGB pr tasarm, ya da pr gereklilik belgesi deildir, s u u g her ikisinin birleimidir. Hem uzerinden deme artlarn tanmlayan bir kons o s trakt imzalanabilecek bir belge, hem de programclarn alp (mimariyi gznne o o u alarak) gereklilikleri gelitirmeye balayabilecekleri bir kayttr. UGB kalems s lerini yle sralayabiliriz: so Gereklilikler Gri ekranlar Ekranlar aras gei diyagram cs Dzyaz olarak detaylanm gereklilikler u s Teknik mimari Yazlm mimarisi Sonu donanm mimarisi c Veri taban emas s UGB ncelikle bir giri blm iermelidir. Bu girite, projenin misyonu ve o s ou u c s zmeye alt sorunlar zet olarak anlatlmaldr. Projenin teknik nkabulco c s g o o leri paylalmal, ve sistem hakknda genel bir kir verilmelidir. s Gri ekranlar blmnde, formlar (veri giri ekranlarn) detayl alanlaryla ou u s beraber belgelememiz gerekecektir. Gri ekranlar, isimlerini renksiz ve skc olmaktan alrlar, unk tek amalar sistemizin veri alveri gerekliliklerini belc u c s s gelemektir. Gri ekranlara bakarak tm veri giri gerekliliklerini grmek mmkn u s o u u olmaldr. Unutmayalm ki bu gri ekranlarnn, veri taban emas tasarmna s etkileri olacaktr. 344

Planlama Gri ekranlar kada (ekrana) dkebilmek iin, diyagram uretebilen bir prog o c gram kullanmamz gerekir, piyasada birok gri ekran hazrlayabilen urn mevc u cuttur. Bu urnler ile ekranlar ekran alanlarn gsterip, belgemizin iine u o c ekilleri grak olarak ekleyebiliriz. s Ekranlar teker teker tamamlandktan sonra, kubak seviyesinde (alan des s taylarn gstermeden) sadece hangi ekrandan hangisine geilebileceini gsteren o c g o bir byk diyagram hazrlanmaldr. Bu diyagram, bir ekrandan dierlerine u u g yaplmas mmkn olan tm geileri gstermelidir, ve btn olarak bakldnda u u u cs o uu g bir a gibi gzkecek diyagram, tm geileri gstermi olacaktr. Bylece ust g o u u cs o s o seviyeden bakarak uygulamada nereden nereye gidebileceimizi anlamamz rag hat olur. Ardndan, dzyaz olarak anlatlacak gereklilikler blm gelmelidir. Her u ou u gereklilik ayr bir blm (section) iinde, dzyaz olarak anlatlmaldr, ve bu ou c u anlatm mmkn olduu kadar detay iermelidir. Bu belge uzerinden kodlama u u g c yapacamz unutmamamz gerekir. Belge hazrlanrken birok git/gel, istiare, g c s yeniden konuma ve al/ver (tradeo) karar yaanacaktr, unk mteri kendi s s c u us iin iyi olacak gerekliliklere karar verme basamaklarndan gemektedir, ve bu c c salkldr. Belgeleme sreci, yapmas istenen eyi, yni iletiimi faydal ynde g u s a s o kanalize edici, ve en sonunda kaydedici roln oynamaktadr. Planlama takm u u bu noktada mteri iin uygun tavsiyeleri ortaya koymal, ve gereklilikleri us c mteri iin yararl ve teknik olarak yaplabilir (feasible) yne doru itmelidir. us c o g Gereklilikleri toplarken, dzyaz ya da ekranlar formatnda, planlama takmnn u yatlandrma dunmemesi iyi olur. Unutmayalm ki mteri, eer kendi nceus us g o liklerini iyi anlamsa, en ok kr getirecek en az yazlm dunyordur, ve s c a us u bu ynde ak tavsiyeler almak onun iin faydaldr, ve yat ancak bu gereklilik o c c listelemesi bittiinde ve teknik mimari ortaya ktnda o projenin ne kadar g c g srecei (programc saysn ve kalitesine oranla tabii) belli olacaktr. Bu noku g tadan nce, uygun gerekliliklerin listeye eklenmesi zaman argmanyla engelo u lenmemelidir. Bir zelliin dahil edilmesi ya da edilmemesi, yaplabilirlik, ve o g ie faydas erevesinde olmaldr. Mteri nasl olsa bir yat grdunde, ve s c c us o ug o yat yksek gelirse kendiliinden gereklilik tralamaya balayarak, daha az u g s s nemli zellikleri atmak isteyecektir. o o Teknik mimari, gereklilikler toplanrken arka planda teknik lider tarafndan yava yava piirilecektir. TL eer bir karara yaklatysa, mimariyi paralelde, s s s g s gereklilikler toplanrken bile belgelemeye balayabilir. UGBnin mimari alkal s a blmnde hem yazlm mimarisi hem de sonu ortamnn yaps (donanm) ou u c ortaya kmaldr, yni lekleme (scaling) bu aamada yaplacaktr. Bu amala c a oc s c teknik lider mteriye, sistemin kullanm seviyesi hakknda sorular sormaldr. us Sistem, ezamanl ka kii, gnde toplam ka ziyaret iin hazrlanmaktadr? s c s u c c Kullanm dzenleri (access patterns) nasldr; Her dakika, saat, gn iin eit u u c s midir, yoksa belli baz zplama noktalar (peak) olacak mdr (mesel bir ieki a cc c sitesinin sevgililer gnnden bir gn nce yksek zplama yapmas, ama dier u u u o u g gnler olduka bo kalmas gibi). u c s Veri taban emas ise, gri ekranlarn bir sonucu olarak ortaya kacaktr. s c 345

11. PROJE YONETIMI Gereklilikler ve Tasarm Gereklilikleri dz yaz olarak yazmann nemini bir kere daha vurgulamak istiyu o oruz, unk gerekliliklerin en nemli grevi mterimiz ile aramzda bir iletiim c u o o us s format olmaktr, ikincil olarak, gelitirme takmna ne yapacan anlatmaktr. s g Baz planlama yaklamlarnda, gereklilik belgesini, koda yakn bir ekilde ve s s kodun ne yapacan birebir tarif etmeye uralmas tavsiye edilir. Bu tamamen g g s gereksiz, ve zaman israf saylabilecek bir ilemdir, unk kodlama, o ii yapan s c u s programclarn iidir ve kod miktar bakmndan en fazla yer tutan blm olan s ou gereklilik kodlarnn iki kere yazlm olmas (birincisi belgede dieri kodda), s g hem uyum asndan hem de efor asndan zarar verecektir. Analizcinin proc c gramcya gereklilii hata brakmayacak ekilde trif etmesi iyi bir ey olarak g s a s pazarlanabilir, fakat kaynak asndan analizci, en fazla birka kii olabilir, ve c c s bu birka kii neredeyse uygulamay belge iine yazarken, programclarn kec s c narda durup bunun bitmesini beklemeleri gerekecektir. Hz, gnmz i dnyasnda u u u s u en nemli faktr olduu iin, programclarn kodlamaya gereklilikleri okuyarak o o g c ve mimariyi dikkate alarak balamas, en uygun seim olacaktr. s c

11.2.3

Kaynaklar, Zaman, Kalite, Fiyat

UGB hazrlandktan sonra yazlm takmnn ynetim grubu, teknik liderin kono trolnde, kaynak ayrm, zaman karar ve yatlandrma ilerine balayabilir. u s s Kaynak ayrm irket iinden programc (kaynak) bulmak, yatlandrma ise s c mteriden istenecek meblaa karar vermek iin yaplacaktr. Danman irketleri us g c s s iin kaynak ayrmnn yat uzerinde etkileri vardr, unk danman irketleri c c u s s aslnda kendileri iin alan programclarn zamann mterilerine satmakc c s us tadrlar. Eer bir yazlm projesi mterinin irketindeki programclara yaptrlacaksa g us s (in-house development) o zaman bu aamada tek yaplmas gereken kaynak ve s zamana bakmaktr, unk programclarn maa nasl olsa mterinin kendisi c u s us tarafndan verilmektedir. Danman irketlerde, kaynak planlamas asndan yaplmas gereken tek s s c ey teknik liderin kendi irketi iinde bir kaynak kapma sava vermesidir. s s c s Eer danman irkette birden fazla proje uzerinde allmakta ise, norml g s s c s a olarak herkes en iyilerle ve en yeterli sayda insanla almak istedii iin, c s g c kaynaklar uzerinde dier projelerle giriilen kran krana bir kapma sava g s s s yaanabilecektir. Dot com yllarnda danmanlk yapan bir irketimizde grevlendirme s s s o toplantlar (stang meeting) kann gvdeyi gtrdu (!) toplantlar hline o o u ug a gelmekle unlyd. u u Bu kapma sonucu teknik lider belli sayda adamlar projesine katar. Simdi s bu adamlarn says ve yetenek seviyeleri uzerinden, bir zaman ve ona gre bir o yat karar verilebilir. Bu irdeleme programc X, Y, Z arasndan, X senior ve Y, Z junior ise, A gereklilik listesi 4 ayda biter gibi bir izgiyi izler. Danman c s irketi her programc tipi iin bir yat izelgesi hazrlamtr, ve X, Y, Znin s c c s harcayaca 4 ay iin mteriye bir yat biilir. g c us c 346

GELISTIRME ORTAMI Ve bu, planlamann olmas gereken eklidir. Bu yaklamn tersi, yazlm ust s s irket ynetiminin bir projeye ok muhta olup imkansz bir biti zaman iin s o c c s c mteriye direk sz vermesi, ve bir de ek kaynak vermeden teknik lidere prous o jeyi bir ekilde bitirmesini istemektir. Kaynaklar ve zaman yakn ilikide olan s s iki vanadrlar; Birinin deiimi tekini etkiler. Ama bu iki vana deimiyorsa, gs o gs uunc bir vana olan kod kalitesi aa decektir. Test edilmeden bittii deklare c u s g us g edilen kod paralar, test evresine girildiinde hla gelitirmesi devam eden c g a s yazlm paralar bu garabetin ba gstergeleri saylrlar. Bunun yapldn c s o g sektrde ne yazk ki pek ok kez grdk. Umarz bu alanda iyiye doru bir o c o u g gidi yaanr. s s Bilinli bir ekilde bir vana olarak gstermediimiz dier bir oynama nokc s o g g tas (dokunulmamasn umarak), programcnn i saatinin arttrlma vanasdr. s Vana olarak gsterilmemitir unk programc saatinde oynama yapmak, kaliteo s c u sizlik ile toplanarak programcnn stresini arttrc bir rol oynayabilir. Psikolojik olarak programclar proje daha balamadan ge kaldklarn hissederler ve s c srekli kovalama oyunu oynadklar bilinciyle tm potansiyelleri ile alsamazlar. u u c Belli bir ya seviyesindeki programclarla bu oyunu oynamak mmkn olabilir, s u u fakat bir sre sonra bu oyunu oynayacak programc bulmakta zorlanabiliriz. u Talebin olduu bir piyasada, programclar daha az stresli alabilecekleri yerg c s lere geeceklerdir. c

11.3

Gelitirme Ortam s

Gelitirme ortam, kaynak kod deposu, test makinalar, test veri taban, hata s takip sistemi ve programclarn makinalarn ieren sistemler ve urnler topluluudur. c u g Bu blmde, gelitirme ortamn oluturan sistemlerin kurulmas ve aralarndaki ou s s ilikinin nasl olmas gerektiini ileyeceiz. s g s g Her projede, uzerinde kaynak kod deposu (mesel CVSin) alaca bir a c s g makina gereklidir. Bu makina, herkesin gelitirme ortamnn balanp en son s g kodu alp geri verebilecei bir merkezi yer olmaldr. Genellikle bu makinann g uygulama servisi ve veri taban test makinalarndan ayr olmas tavsiye edilir. Bu makinann uzerindeki kod depolarnn yedeklenme ii dzenli olarak yaplmaldr. s u Programclarn gelitirme makinalar (hesaplar), merkezi depoya iaret s s eder, ve tm kod alma/verme ilemleri, bu depo uzerinden yaplr. Test iin u s c ortaya kartlacak srm, mteriye projenin sonunda gnderilecek nal urn, c uu us o u hep bu merkezi depodan ekilen kodlar baz alnarak yaplmaldr. Tm kodun c u en son hli, sadece kod deposunda olmaldr. a Programclarn hususi gelitirme ve test ortam iin iki trl ziksel yap s c u u mmkndr: u u u Unix makinalara login ederek, onlar uzerinden gelitirme ve test s Windows makinalarda gelitirme ve Unix uzerinde test s 347

11. PROJE YONETIMI Bu anlatm, dolayl olarak u nkabulu ierir: Her programcya ayr bir test s o c ortam gereklidir. Bu test ortam, genellikle, Unix uzerinde olur, unk sonu c u c (production) makinas bir Unix makinasdr. Test ortamnn sonu ortamna c mmkn olduu kadar benzemesi, uzerinde kodun ileyecei nal ortamda u u g s g kabilecek hatalar nceden yakalama bakmndan ok nemlidir. Projemizde c o c o iletim sisteminden ilerkod seviyesinde bamsz olan Java dilini kullanyorsak s s g bile, bu durum byledir, unk baytkod ayn bile olsa, JVMler ayr iletim siso c u s temlerinde almaktadr. Bir Murphy kanununa gre ters gidebilecek herey c s o s ters gidecekse, o zaman tm potansiyel terslikler (bir JVMde alan kodun u c s teki iletim sistemindeki JVMde almamas ihtimali) nceden test edilmeo s c s o lidir. Eer Unix uzerinde gelitirme yapyorsak, bu birden fazla programc ayn g s makinada kodlama yapyor demektir, ve bu sebeple A.4.2 blmnde anlatld ou u g gibi herkesin uygulama servisi (mesel JBoss) iin ayr ayr portlar kullana c mamz gerekir. Programclar ayr Unix hesaplar ile merkezi gelitirme makis nasna girecekler, ve oradaki ortamlar (javac, editr, vs) ile gelitirmeyi yapp, o s depoya o ortamdan son stabil kodu gndereceklerdir. o Eer gelitirme Windows, test ortam Unix ise (yni potansiyel JVM farkllklarndan g s a kabilecek hatalar gze aldysak), gelitirme ortamnda port ayrm yapmamz c o s

Sekil 11.1: Gelitirme Ortam Fiziksel Yaps s 348

GELISTIRME ORTAMI gerekmez unk herkesin makinas ayrdr ve bu yzden bu makinalar ayn c u u portlar kullanabilirler. Fakat test makinas merkezi olacaktr, ve bu sebeple A.4.2 blmndeki port ayar deiikliini test makinas iin yapmamz gerekir. ou u gs g c Unix uzerinde, gelitirme ya da test amal birok kullancy ayn makinada s c c desteklemek iin teknik lider u prensibi takip etmelidir. Gelitirme ve test c s s amalar iin her programcya c c

Sekil 11.2: Gelitirme ve Test Sras s

Bir Unix kullancs (kendi adnda) O kullanc uzerinde ileyen bir JBoss srecine ayr bir port s u Uygulamann kullanaca ayr isimli bir veri taban emas (kullancs) g s tahsis edilmelidir. Tm bu birimlerin herkes iin ayr olmas ok nemlidir! u c c o Yoksa, ayn anda ayn makinada gelitirme ya da test yapmann imkan yoktur. s 349

11. PROJE YONETIMI Ayr port/kullanc/sre sistemi, tm programclara ve testilere birbiru c u c lerinden izolasyon salayarak, herkese kendi gelitirme/test ortamn verir. Insanlarn g s bir test yapmak iin birbirinden izin istedii, ya da istemeden direk kullanmaya c g balayarak birbirlerinin sonucunu etkiledii bir sistem optimal-alt, hatalara s g ak ve hibir irketin takip etmeyecei bir yntemdir. c c s g o Veri taban, ziksel olarak, uygulama servislerinin iledii test Unix makis g nasnda olabilir.

11.3.1

Test Ortamna Deployment

Gelitirme sreci iinde uygulama belli bir olgunlua eritii zaman test iin s u c g s g c en son kodu test makinasna gnderme ii teknik lider tarafndan zel scriptler o s o kullanlarak yaplr (blm 6.1). Eer programclar Windowsda alyor ve ou g c s hepsinin ayr bir Unix makinasnda test hesaplar var ise, bu scriptler zaten programclarn kendi testleri iin srekli kullanlmaktadr, teknik lider sadece c u bu kod gnderim ilemini testi iin ayr bir Unix hesabna, JBoss portuna ve o s c c veri taban kullancsna doru yapacaktr. Kodlarn gelitirme ve dier ortamg s g lar arasndaki hareketi, Sekil 11.2 uzerinde gsterilmitir. o s Ek olarak teknik lider, kod depo sisteminde gnderilen kodun gnn beo u u u lirten bir etiket atlmaldr, unk bu srme sonradan dnmek gerekebilir. c u uu o Bu yapldktan sonra, artk en son kodlar ieren test hesabnda uzerinden c test servisi balatlr, ve kabul testlerini iletmekle grevli kii bu servis uzerinde s s o s testlerini yapmaya balar. Bulunan hatalar hata takip sistemine girilecektir. s Projenin kaynak kod dizin aacnda bulunmas gereken nemli scriptler, g o Kod gndermek o Veri tabann sfrdan kurmak Test verisi yklemek u iin yazlm scriptlerdir. Kitabmzn rnek projelerinde veri taban scriptleri c s o src/sql altndadr. Bu scriptler .sql dosyalarnda bulunurlar ve test makinasna her kod gnderildiinde test makinasnda iletilerek en son kodun en son o g s ema ile almas salanmaldr. Bu beyann bir yan sonucu olarak, emann en s c s g s son hlinin her zaman sql dosyalarna yazlmas gereklilii sonucuna varrz; a g Sema ile kodun arasnda olmas gereken birebir iliki barizdir, ve bu iki taraf s senkron halde tutmaya dikkat ederek, en son kodun eski bir ema uzerinde test s edilmesini engellemi oluruz. Hatt teknik liderin koyaca nemli davran kus a g o s rallarndan biri bu olmaldr: Her ema deiiklii ilk nce src/sql altndaki s gs g o scriptler iinde yaplmal ve bu deiiklii kullanan kodlar ile birlikte KKIa c gs g ayn anda eklenmelidir (check-in). Sema deiii hibir zaman test veri ta gsg c ban uzerinde direk olarak yaplp, orada braklmamaldr. Sema, kodumuzun ayrlmaz bir parasdr. c 350

GELISTIRME ORTAMI Kod deposu, uygulamann almas iin gereken her trl metni ieren bir c s c u u c merkez olmaldr. Kod gnderme iin gereken script, mesel deploy.sh adnda ve src/ o c a scripts dizini altndaki olabilir. Bu script parametre olarak deploy edilecek makinann ismini, ve Unix hesap ismini alabilir. Bunlar kullanarak, nce kod o deposundan en kodu alacak, Ant ile derleyecek, scp ile derlenen kodlar test ortamna gnderecek, ve test veri tabanndaki emay silbatan yaratp (CREATE o s s TABLE komutlar ile) test verisini ekleyecektir.

11.3.2

Kaynak Kod Idaresi

Kaynak kod idaresi (KKI) sistemi bir projede alan tm programclarn yazd c s u g kodun ve scriptlerin metninin muhafaza edildii yerdir. Bu merkezi yere olan g gereksinimimiz, birok programcnn ayn anda ayn yerdeki kod uzerinde yapt c g deiiklikleri gnderebilme ihtimalinden ortaya kmaktadr; Eer ayn dosyay gs o c g birden fazla kii deitirmise, KKI bu akmalar zecek teknolojiye sahiptir. s gs s c s co Ayrca KKI tarihi bir ariv niteliini tar. Bu akll depo, bir kod parasnn s g s c uzerinde yaplm olan tm deiiklikleri hatrlayabilir. Eer kod paras Xin s u gs g c 2, 3, 10 gn nceki hline dnmek istiyorsak, bu KKI sistemleri iin ok bau o a o c c sit bir ilemdir. Bunu yapmak projelerde ok sk olmasa da, arada yaplmas s c gerekebilir ve gerektii zaman KKI tarafndan desteklenmesi istenir. g zellikleri kaynak kodlar yedekleme, belli bir tarihteki Dier aranan KKI o g tm kodlara iaret atarak o gnn kodunu dondurma (labeling) ve dallanu s u u mak (branching) gibi zelliklerdir. Bunlarn CVS ile nasl yaplacan ileri o g blmlerde ileyeceiz. ou s g CVS, urn olarak piyasadaki en rahat eriilebilir, yat uygun (bedava) u s ve hakknda yaygn kaynak olan KKI sistemidir. Son zamanlarda Subversion adl ak yazlm urn de poplerlik kazanmaya balamtr. Ak yazlm proc u u s s c jelerinin neredeyse tamam CVS kullanr, bunda CVSin programclara kopuk (disconnected) ekilde almasna verdii destek byk rol oynamtr (yat s c s g u u s ikinci bir etkendir). Kopuk alsma, sadece Internet uzerinden iletiim kuran ve deiik blgelc s gs o erden programclarn beraber almasn artrr, fakat kopuk alma ayn c s c g s c s blgede, ayn odada alan programclar iin bile istenen bir zelliktir. CVS o c s c o ile bir dosyay deitirmek iin kitlememiz gerekmez, ve bakas ile ayn anda gs c s yaptmz deiikliimizi CVSe ayn anda geri koymaya urarsak CVS bir g gs g g s akma (merge conict) mesaj alrz. Bylece CVS ikinci deiikli gnderen c s o gs g o kiinin akmay zmesini bekler. Bu durum, ayr bir dnya iin olsa da, 3.8.3 s c s co u c blmnde uygulama ve veri taban arasndaki aksma zme dinamiine ok ou u c co g c benzer. Ve uygun zm ne kadar ilgin ki tekrar iyimser kitleme (optimistic co u c locking) ynnde olmutur, yni burada da zm akmay sonradan zmek o u s a co u c s co ynndedir. Iyi kirlerin srekli ortaya kma gibi bir adetleri vardr. o u u c 351

11. PROJE YONETIMI Ilk Kod Deposunu Hazrlamak CVS kurmak iin A.10 blmne bavurunuz. KKI sistemi iin nce bir depo c ou u s c o yaratmak gerekir. Bu depo, btn kaynak kodun sakland yer olur. Projenin uu g ilk kodunu sisteme eklemek iin, CVSin olduu makinaya balanp (yni CVSc g g a ROOT deikenini o makinadaki depoya set edip), cvs import komutunu kulgs lanmalyz. Bu komut, sadece projenin banda gereklidir. Teknik lider pros jenin dizin yapsn, Ant scriptlerini, mimari iin gereken Java dosyalarn, ve c jar ktphanelerini kendi yerel makinasnda hazrladktan sonra bu yapnn uu tamamn CVSe koymak isteyecektir. O anda CVS bombotur, ve ilk giren s kod bu kodlar olacaktr. Bu durum tipik bir cvs import gerektiren bir durumdur. Teknik lider, eer projeyi /usr/local/proje1/ altnda kurdu ise, nce o dizine gider, ve u g o s komutu iletir. s
cvs import -m "Proje Ekleniyor" havuz_ismi vendortag releasetag

Bu komut, havuz_ismi iin ne kullanldysa, o isimde bir kod havuzu CVSte c yaratacaktr, ve /usr/local/proje1 altndaki btn kodlar oraya koyacaktr. uu Bu komutu kullanrken, CVSROOT deikeninin doru ayarlanm olduunu gs g s g farzediyoruz. CVS kurmak ile ilgili A.10 blmnde, havuzun ziksel adresini ou u tamak iin -d yaklam yerine CVSROOTun daha iyi olacan belirtmitik. s c s g s Bir nemli not daha: cvs import, (teknik lider iin) /usr/local/proje o c 1 dizinini gelitirme yapmaya hazrlamaz, sadece o kodu ieri koyar. Yani, o s c kodu ieri koyan teknik lider cvs commit, cvs update gibi komutlar kullanmak c istiyorsa, nce cvs co havuz_ismi komutunu iletmeli ve kodu aynen teki o s o programclarn yapaca gibi dar ekmelidir. Bunu ya ayn dizinde, ya da g s c baka bir dizinde yapabilir. s Dallanma (Branching) ClearCase kullanlan bir projede alm olanlar, branch kullanmnn ne kadar c s s fazla olduunu gzlemlemitir. ClearCase, branch yaratmay ve kullanmn g o s byk lude rahatlatr. ABDde byk beli diye bilinen danman irketlerinden u u o c u u s s s (Deloitte & Touche, Ernst & Young, KPMG, PriceWaterhouseCoopers and Accenture) gelen arkadalarda bu derin ClearCase etkisi ile bir branch kltr hisseders u uu siniz. Bu irketlerdeki ClearCase kullanmnn sebebi, byk projeleri idare ets u u mek iin eskiden ClearCaseden daha profosyonel bir aracn olmamasdr. Bu c irketler de yazlmda eski ve kkl irketlerden saylrlar. s o us ClearCaseilerin de ok branch kullanmalarnn sebebi de aslnda udur: c c s ClearCase de alrken, bir dosya uzerinde almak iin nce onu kitlemeniz c s c s c o gerekir. Eer branchler olmasayd, ayn kod uzerinde alan programclar ayn g c s anda, ayn dosya uzerinde alamaz olurlard. Bu da kabul edilmez bir durum c s s dur. Ite bu sebeple de ayn dosya uzerinde almas muhtemel olabilecek ayn c s takmn programclar, kendileri iin ayr birer branch yaratma yoluna gider c 352

GELISTIRME ORTAMI olmulardr. Yni kii bana branch yaratmak, ClearCase kodcular iin bir s a s s c lks deil, aslnda bir zorunluluktur. u g Fakat ak yazlm, kendisi ve kltr ile bu yaklam deitirmeye balad. c u uu s gs s Oncelikle, CVS kopuk (disconnected) almaya uygun bir ara olduu iin, bu c s c g c stil, dnyann herhangi bir yerinde olabilecek ak yazlmc iin daha uygun u c c bir model olmutur. CVSte bir dosya uzerinde almak iin onu kitlemeniz s c s c gerekmiyor. CVS, herkesin ayn dosya uzerinde deiiklik yapmasna izin verir, gs ve bu sebeple olabilecek, yni ayn dosyay birka kiinin deitirmesinden ora c s gs taya kabilecek, akmalar (merge conicts) nceden engellemek deil, sonc c s o g radan, commit annda kontrol etmeyi seer. Cakmalar zmek, biraz CVSin c s co yardmyla ikinci deiiklii yapan programcya kalr. gs g Ornek: A ve B tm kodu checkout ederler. A dosya Xi deitirir. B Xi u gs deitir. A commit eder. B commit eder, ve B akma hatas grr. Bu akmalar, gs c s ou c s cvs up komutu otomatik olarak zebilir, ve lokal dosyasnda, gzelce formatco u lanm ekilde hangi parann hangi kodcudan geldiini gsteren bir ekilde bir ss c g o s otomatik birletirim (auto merge) sonucu grecektir. Ama i bitmi deildir, s o s s g nal bir versiyon iin bu paralardan birinin ya da tekin seilmesi, ve bu c c o c nal versiyonun CVSe commit edilmesi gerekir. Ancak bu yaplnca i tamams lanacaktr. CVS ClearCaseden kitleme balamnda deiik olmasna karn, bu, CVSte g gs s hi branch kullanlmayaca anlamna gelmez. Evet, CVS projelerinde branch c g kullanm daha azdr, ama gereksiz deildir. O zaman u sorularn cevabn g s verelim: CVSte ne zaman branch yaratmak gerekir, ya da daha genel anlamnda bir yazlm projesi ne zaman branch yaratmaldr?. Ne kadar sklkla branch yaratlmaldr? Branchlerle alkal hangi disiplin takip edilmelidir; Yni branching yaplarmz, a a yapmalarmz nelerdir? Ilk soruya cevap verelim. Baz artlar vardr ki, branch kullanm kanlmazdr. s c Mesel, 2004-10-02 tarihinde HEAD uzerinden bir srm yaptnz ve yazlmn a uu bir sonraki zelliklerini eklemeye devam ettiniz, haftalar geti ve kodcularnz o c tam gaz gidiyorlar. CVSi kullanma stiliniz yle: Kodun son hlini HEAD so a uzerinde tutuyorsunuz, programclar kodlarn son hlini buraya commit ediy a orlar. Fakat, birden bir kullancnz (user) haftalar nceki 2004-10-02 srmnde o uu u bir hata buldu. Fakat yle bir ey ki, siz yeni versiyon iinde zten bu hatann o s c a olduu modl tamamen deitirmektesiniz, yni hata veren kod ortalkta yok! g uu gs a Bu hatann tamir edilmesi ve kullancya yeni bir srm verilmesi gerekiyor. uu Ne yapacaksnz? Tamir edilecek kod artk HEADde deil, ya da orada, ama g uzerinde baka bir ey eklenmekte, yni alma hlinde. s s a c s a 353

11. PROJE YONETIMI s Ite bir branch, bu klasik derde bir devadr. Prensip olarak, srm yaplnca uu (rneimizdeki 2004-10-02 tarihi) kodun o andaki haline CVSte bir tag (etiket) o g atlr. Ve bundan sonra gelitirmeye HEAD uzerinde devam edersiniz. Bu sayede s hata raporu gelince, tag koyulan yere geri dnebilirsiniz. Hatay tamir iin, o c HEADi etkilemeyecek bir yan dal amanz gerekir, yni bir branch. Simdi c a hatay, bu branch uzerinde tamir edip, commit etmeniz mmkndr. Bu deiiklik u u u gs HEAD tarafndan grlmeyecektir. Bu durum HEAD uzerinde yeni zellikleri ou o ekleyen arkadalar mutlu eder, unk kendi hllerinde ilerine devam etmek s c u a s isterler. s Ite branchin faydas budur. Bir branch, herhangi bir zamanda HEADin sanal bir kopyasdr, ve o andan itibaren ondan bamszdr. Branchler sayesinde g HEADi teki branchlerden izole edebiliyoruz. Yan detay olarak: bir branch o HEADden olduu gibi baka bir branchten de alabilir, CVS buna izin verir, g s c ama bu yaklam tavsiye etmiyoruz. Bir branchi sadece HEADden amalyz. s c Hata tamir senaryomuza dnersek; Diyelim ki, 2004-10-02 branchi uzerinde o yaplan deiiklik projenin en son hlinde isteyeceimiz bir zellik. Yni eer gs a g o a g yaptnz dzeltmeleri HEAD uzerine de koymak istiyorsanz, bunu merge g u ilemi ile gerekletirebilirsiniz. Bu ilem, cvs up yaptmzda olan merge ileminin s c s s g s branch-leraras bir karldr. Aynen normal CVS kullanmnda olduu gibi s g g eer akmalar olursa, CVS sizi uyaracaktr. Bu ilem iin gereken komutlar g c s s c daha sonra greceiz. o g Branchler ile almaya baladnzda, zellikle Kaynak Idare Lideri (KIL) c s s g o olan siz, birden fazla olacak branchleri hatrlamak ve ismine bakarak ne iin c yaratlm olduunu abuka anlabilmek iin bir isimlendirme stratejisi gelitirmek s g c c c s zorundasnz. Tavsiyemiz bu ismin, aadaki her kavram iin dierlerinden ile ayrlan s g c g bir kelime kullanmasdr. Bu kavramlar Sabit bir nek: Ismin branch olduunu belirten B har, ya da tag iin o g c T. Proje safhas: (ALPHA, BETA, RELEASE) Bir ayra: KKI tarafndan ya da kullanc tarafndan kararlatrlr. 1,2,3 c s ya da ONCE, SONRA, kullanc ismi, vs. Tarih: (YIL-AY-GUN olarak, rnek: 2004-10-20) o Ornek olarak, BETA safhasnda yarattmz bir branch ismine bakalm: g B_BETA_1_2004_10_22. Bir branch yaratmak iin, cvs tag komutunu kullanmamz gerekiyor. Bu c durum, cvs tag komutunu daha nce salt etiketlemek iin kullanlar iin biraz o c c garip gelebilir. Fakat tarihi bir takm sebepler yznden durum byledir. u u o Branche dnelim: Bata bahsettiimiz senaryo balamnda tag koyma ii o s g g s (pr etiket), branchin kendisinden muhakkak daha nce gelecektir. Her reu o leaseden sonra, muhakkak tag atmay unutmayn! Eer dnecek iaretiniz g o s 354

GELISTIRME ORTAMI yoksa, o noktadan branch amanz imkansz hle gelir. Projenin nemli kiloc a o metre talarn bir tag ile iaretlemeyi alkanlk hline getirin. s s s a Orneimize dnelim: Bu ekilde atlm olan tag isminin T_RELEASE_1_2 g o s s 004_10_22 olduunu farzedersek, nce o tage dnp, yeni bir alma dizinini g o o u c s sadece o tag iin checkout etmemiz gerekecektir. c
cd /vs/vs/proje1/ cvs co -d eski_release -r T_RELEASE_1_2004_10_22

Simdi bu alma dizini iinden bir branch oluturabiliriz. c s c s


cd /vs/vs/proje1/eski_release/ModulIsmi cvs tag -b B_RELEASE_1_2004_10_22

Bylece srmn yapld anda tanmlanm tag uzerinden artk bir branch o uu u g s yaratm oluyoruz. Artk deiikliklerimizi bu branch uzerinden yapabiliriz. s gs Fakat dikkat! Hlen branch uzerindeki kodlar gsteren bir alma dizini a o c s iinde deiliz. Bu alma dizinini yaratmak iin, cvs co komutunu kullanmamz c g c s c gerekiyor.
cd /vs/vs/proje1/ cvs co -d Relase1Branch -r B_RELEASE_1_2004_10_22

Tamam. Artk /vs/vs/proje1/Relase1Branch altnda branch kodlar uzerinde istediimiz dzeltmeyi yapabiliriz. Gelitirme srasnda artk tamamen ayr bir g u s branchte olduunuza gre, istediiniz kadar checkin yapabilirsiniz. Bu comg o g mitler sadece branchinize gidecektir, HEAD etkilenmeyecektir. Deiim bitgs tikten sonra, nce update sonra commit yapmalsnz. Her committen nce o o update yapmay da alkanlk hline getirin. Bu sayede ayn branch uzerinde s a olabilecek akmalar grebilirsiniz. c s o
cd /vs/vs/proje1/Relase1Branch/ModulIsmi cvs -q update

Merge akmas gelmedi ise, commit edebiliriz. c s


cvs ci -m "Hata no 3342 tamir edildi" ... ... (commit kts) c ... ...

Orneimizin banda, tamir edilmesi gereken kodun artk ortada bile olmayag s bileceini sylemitik. Bu durumda HEAD branch herhalde yaplan tamire g o s ihtiya duymaz. Siz de tamiri branch iinde brakr ve bir daha onu kullanc c mazsnz (branchi silmeyin). Fakat durum yle olabilir ki (ve ounlukla byle o c g o 355

11. PROJE YONETIMI olacaktr) yaplan tamir HEAD uzerinde de yaplmaldr. Hata raporu release tarihine olduka yakn olabilir ve gelen rapor HEAD uzerindeki yeni zellikleri c o bile etkiliyordur. Bu durum, branchten HEADe merge yapmamz gerektiren bir durumdur. Bu noktada, eer ayn deiiklii HEAD uzerine nasl olsa geireceksek, g gs g c niye bu i iin bir branch atm. Release tagdeki hlimize dnp, orada tamir s c c a o u yapabilirdim diye dunebilirsiniz. Bu dunce u sebeple geersizdir. us us s c 1. Release tag uzerinde kod deitirirseniz, tag, hareketli bir tag olacaktr. gs Halbuki release tagi, kodun belli bir anda taa kaznm hli olmaldr. s s a Siz deiiklikleri release tag ustnde commit ederseniz, kodun ilk regs u leasedeki hline bir daha asla dnemezsiniz. Zaten ihtiyacm olmaz dea o meyin. Gerekebilir. 2. Branch uzerinde tamir yapmakla, istediiniz kadar commit etme, ve gnlerce g u bu branchte kalma lksne kavumu oluyorsunuz. Ne siz HEADi, ne u u s s HEAD sizi etkiliyor. Tamam. Simdi HEADe merge tekniini grelim. Biz de bir gelitirici olduumuza g o s g gre, HEADe iaret eden yni en son kodlar ieren bir alma dizinimiz olao s a c c s caktr. Yoksa yaratalm. Mergee balamadan nce de cvs up -d ile gncelleyes o u lim. Bu dizin iine gidelim, ve nce update ile akmalar grelim. Cakmalar c o c s o s zdkten sonra da commit (ci) ile ii bitirelim. co u s
cd /vs/vs/proje1/HEAD/ModulIsmi cvs -q update -j B_RELEASE_1_2004_10_22 cvs -q ci -m "B_RELEASE_1_2004_10_22 Branchinden Merge Edildi"

Bravo. Ilk merge gerekletirdiniz. u c s Bu merge bittikten sonra, eer ayn branchi ileride tekrar kullanmak isg tiyorsanz, nemli bir uyarda bulunmak isterim. Ayn branchten HEADe o birden fazla merge yaparsanz (tabii ki yeni deiiklikler ve yeni bir commit gs yaptktan sonra), bir srprizle karlaacaksnz. CVS, daha nce yaptnz u s s o g deiiklikleri tekrar merge etmeye alsacak! Ve bu sebeple warning: conicts gs c during merge mesajn grrsnz. Bunun sebebi, CVSin son yaptnz comou u u g mitlerin kmesi diye bir anlaynn olmamasdr. CVSe gre, beraber comu s o mit olmu dosya A,B,C arasnda hibir balant yoktur. Merge ileminin tari s c g s de branchin ust noktas ve HEAD arasndaki farkn uygulanmas olduuna g gre, ust nokta, ayn deiiklikleri ierecektir, ve akma ortaya kacaktr. o gs c c s c Bu problemin ustesinden gelmek iin, CVSe biraz yardm etmemiz lzm. c a Branch uzerinde ilk tamiri gerekletirdikten sonra branch uzerine bir tag c s koyun. Ismi, mesel, B_RELEASE_1_2004_10_22_tamir_1 olsun. a Bylece Ikinci tamiri yaptktan (ve commit ettikten sonra), CVSe bu o tagten nce yaptklarm istemiyorum diyebilirsiniz. Bunun iin (HEAD alma o c c s dizini iinde) unlar kullanmanz lzm. c s a 356

GELISTIRME ORTAMI
cd /vs/vs/proje1/HEAD/ModulIsmi cvs -q update -j B_RELEASE_1_2004_10_22_tamir_1 B_RELEASE_1_2004_10_22 cvs -q ci -m "B_RELEASE_1_2004_10_22 tamir 2 Branchinden Merge Edildi"

Ilk -j balang tamir 1den sonra konulan tagdir, ikinci -j normal branch iss c midir. Herhalde burada alnacak ders u olmaldr: CVSte sk sk tag atn! Bir s release olay, bir branchten HEADe merge olay, ya da bir hata tamiri CVS dnyasnda nemli olaylardandr, ve gnn anlam ve nemini belirten bir tag u o u u o ile kutlanmalar (!) gerekir. Artk setiimiz yolu zetlemeye hazrz. c g o CVSte en rahat gelitirme yolu, programclarn en sonu kodu HEAD s uzerinde gelitirdikleri yoldur. Zten progamclarn alma dizinleri bir s a c s nevi branch gibi de grlebilir. Ama bu yntemi verimli alr hlde ou o c s a tutmak iin, u kurallar sk sk takip edin: c s Programclarnza sk sk commit etmesini syleyin (her gn). o u Programclarnza derlenmemi ve testleri gemeyen kodu commit s c etmemesini tembih edin. Herkesin CVSten en son kodu sk sk almalarn syleyin. o Branchleri zel durumlar (hata tamiri) iin kullann. o c Onemli olaylarda tag atn (hem HEAD uzerinde, hem de branchler uzerinde). Mesel bir release, ya da hata tamiri muhakkak tag gerektiren durumlar a olmaldr. s Iinizin bittii branchi kendi hlinde brakn. Calma dizinini silebilirsiniz g a s (tabii iindeki hereyin commit edildiine emin olduktan sonra). Bu branchi c s g CVSten silmeye uramayn. Tekrar iinize yarayabilir. g s s Kaynak Kodu Etiketlemek Teknik lider, ya da onun eittii ve grevlendirdii projede idari ilere bakan g g o g s arkada, ne zaman test iin nemli bir srm yaplmsa o srmn referans s c o uu s uu u ald o anki kod durumunu dondurmak iin, CVSte bir etiket atmaldr. g c Etiket atmak, bir nevi koda iaret brakmaktr. Bu iarete sonradan dnlebilir, s s o u hatt sadece iarete ynelik cvs commit ilemleri bile yapabilirsiniz. Fakat geri a s o s dnmek, veya hatrlamak iin bu iareti brakmak daha yaygn bir yaklamdr. o c s s Etiketlemek iin, c
cvs tag <<etiket_ismi>>

357

11. PROJE YONETIMI komutunu kullanabilirsiniz. Teknik lider, ne zaman mteriye ve ya byk bir test ynelik bir srm us u u o uu yaparsa, bu etiketleme ilemini gerekletirmelidir. Etiket isimleri, release_1 s c s (srm 1), release_2, gibi isimler, ya da sadece bir numara olabilir. Tarih uu ieren srm isimleri de grmtk. c uu o us u Daha byk projelerde, etiketleme sreci ile hata takip program arasnda u u u ilikinin kurulmas gerekecektir, unk sonuta srm yaplmtr, test makis c u c uu s nasna konulmutur, ve bir sre sonra testi, hata raporlar gndermeye balayacaktr. s u c o s Programc bu hatalar, hangi srmde tamir etmeli, ya da tekrar ortaya karmaldr? uu c Bu gibi durumlarda, ITracker programnn da desteklendii gibi, hatalarn g iinde hangi srmde test edilecei bilgisi kaydedilmelidir. Bu srm nosu, c uu g uu teknik liderin CVSte att etiket numaralarn baz alarak girilen bir numara g olacaktr. Ayrca dier ynde, testilerin o anda hangi srmde olan bir programa g o c uu baktklarn anlayabilmeleri iin (nyze bakarak srm anlayabilmeleri her c o u uu u zaman mmkn deildir), teknik liderin etiket deerini, uygulamann paras u u g g c olan bir statik HTML sayfasna koymas uygun olabilir (mesel src/pages a /version.html gibi. Bu deer gnderimi, etiketleme scriptinin yapaca yan g o g bir ilem olabilir (en uygun yer aslnda orasdr). Srm HTML sayfas, hep s uu ayn yerde, hep ayn isimde olacak bir sayfa olmaldr, ve sayfann tek ierii, c g test edilen o anki kodlarn srm numarasndan ibarettir. Bylece gerektiinde uu o g ismi belli bu HTML sayfasn ziyaret eden testi, test ettii uygulamann c g hangi srmde olduunu rahata anlayabilmi olur. uu g c s

11.3.3

Kod Gzden Geirme Toplantlar o c

Proje takmnda her programcnn belli baz kodlarn gzden geirmek, ve daha o c genel amal olarak takmn kulland teknolojiler hakknda bilgi istiaresinde c g s bulunmak iin, arada srada resmi bir kod gzden geirme (code review) toplantsnn c o c yaplmas gereklidir. Bu toplantdan nce teknik lider hangi programcnn koo dunun gzden geirileceine karar verir, ve bu toplantdan nce program koo c g o dunu yazcdan basarak herkese datr. Kodun her yazc sayfasna iki kod g sayfas decek ekilde ve yatay olarak baslmas iyi olur. Bu ekilde kod basus s s mann tekniklerini A.11 blmnde grebilirsiniz. ou u o Bu gzden geirme toplantlarna herkes bakt kodun uzerine notlar alm o c g s olarak gelir. Toplant srasnda herkes srayla yazd yorumlar kodun sahibi ile g paylar. Programc konu hakknda soru sorar, eer katlmyorsa, cevap verir. s g Teknik lider de konu hakknda yorumlarn ekleyecektir, bylece tm takm o u birbirinden yeni bilgiler edinmi olur. s Ruh hli olarak gzden geirme toplantlar programclar uzerinde stres a o c yaratabilir, unk herkesin nnde kodlar hakknda yorum yaplacaktr, ve c u o u grlen eksiklikler sylenecektir. Tavsiyemiz, programclarn bu toplanty idam ou o mangas nne kyor gibi grmemesidir. Ayrca kod hakknda yorum vereno u c o ler de yapc eletiriler ile toplantya gelmelidirler. Insanlar mekanik hatalar s 358

GELISTIRME ORTAMI yapabilirler (bkz. Kural #4), bunlar zten ok nemli deildir; Ama prensip a c o g hatalar, takip edilmesi gereken mimari kurallarn kontrol kod gzden geirme u o c toplantsnda yaplmaldr. Kodlama standartlarnn takibi de, ayn ekilde, bu s toplantda kontrol edilmelidir.

11.3.4

Kodlama Standartlar

Kodlama standartlar, pr dil seviyesinde konan ve stil ile alkal kurallardr. u a Mesel, if komutlarnda { iaretinin if kelimesi ile ayn satrda m, bir sona s raki satrda m olmas gerektii, bir kodlama standart karardr. Kozmetik g bir karar gibi gzkse de, kodlama standartlar kod bakm iin nemlidir, o u c o unk kodun birok deiik yerine bakarken insann aradn bulma kabiliyetini c u c gs g arttrr. Proje sonunda tm kod sanki tek kii tarafndan yazlm gibi gzkmeu s s o u lidir. Kodlama standartlarn otomatik olarak kontrol etmek istiyorsanz, http ://checkstyle.sourceforge.net/ adresinden Checkstyle adl ak yazlm c projesini alp kullanabilirsiniz. Checkstyle kullanmak iin kurallarn tanmland c g bir ayar dosyas hazrlamak gerekir, ve daha sonra (mesel bir Ant targetinden a ararak) ilettiiniz Checkstyle, tm kodu stil kontrolnden geirecektir. Buc g s g u u c lunan stil hatalar, aynen derleme hatalar gibi bir hata logundan ekrana baslacaktr. Teknik lider kodlama standartlar gerekten takip edilmesini isc tiyorsa, projenin Ant scripti build.xml iinde derleme targetini Checkstyle c targeti ile bir depends ilikisine sokabilir. Bylece derleme yapmak iin stil s o c kontrol kendiliinden olmu olacaktr. u g s Teknik liderler kodlama standartlarn olutururken, programclar ok skacak s c kurallar getirmemelidirler; Genellikle ounluun takip ettigi yntemi kural c g g o hline getirmek en iyisidir. Amacmz kodun ayn gzkmesini salamaktr, a o u g kodculara hi norml gelmeyen kat kurallar koymak deil. c a g

11.3.5

Projelerde Hata Takip D zeni u

Bilgi ilem projelerinde hata takip iin bir sistem kurmamz gereken zaman, s c stabil bir kod baznn ortaya kmaya balad ve sistemi mterilere gsterc s g us o meye baladmz zamana yakn bir yerde olmaldr. Hatalar, herhangi bir s g programcnn herhangi bir kod parasnda (JSP sayfas, Java kodlar, vs.) orc taya km olabilir, ve bu hatalar bulunduu zaman bir yerlere kayt edilip c s g oradan takip edilmelidir. Hatalar (ve bilahere onlarn tamir edilme istei) zag manla biriktike, hangisinin tamir edilmi olduu, test etmeye hazr olduu c s g g gibi konular idare asndan sa yolduracak seviyeye gelebilirler. 20-30 tane c c hata bile, bir hata takip sistemi kurmamz gerektirecektir. Bu hata takip sisteminin ana zellikleri unlar olmaldr. Sistem, o s Programclara atanan/ait hatalar sadece onlara gsterebilmeli o Hatalarn tamir durumunu muhafaza edebilmeli 359

11. PROJE YONETIMI Tamirden sonra tekrar test edilecek hatalarn hangileri olduunu testilere g c gsterebilmeli o Hatalarn testiden programcya, ve tamir edildikten sonra programcdan c testiye geri olan i akn destekleyebilmeli. c s s Hatalarn deiim tarihesini, herkesin dtu notlar kaytl tutabilmeli gs c us ug ve gsterebilmelidir o Bu ana hatlar destekleyecek en iyi uygulama tr, portal eklinde olan bir uu s hata takip sistemidir. Buna karlk, Excel tablolarnda hata takip yapmak s ok klfetli olacaktr, unk bu ekilde tablolarda i ak, tarihe tutmak c u c u s s s c imkanszdr. Tek bir Excel tablosunda birka programcnn hatalarnn en son c durumunu kaydedilip birletirilmesi ok zordur. Portal bazl hata takip pros c gram, her programcya ve testiye bir giri ismi verecek, testilerin yaratt c s c g hatalar programclara gndermesini rahatlatacaktr. o s I Ak s s I aknn genel hatlar yle olur. s so 1. Testi, hata portalna kendi kullanc ismini kullanarak girer ve proc jenin uygulamasnda grdu bir hatay sisteme ekler. Bu hatay, bir o ug programcya atar. 2. Hatay alan programc, o hatann kt kodu yazan, ya da o kodu iyi c g bilen bir baka programc olabilir. Bu programc, gnn herhangi bir s u u saatinde portale girip hatalar listesini kontrol edecektir (ya da hata portalinden otomatik e-mail almtr, portal hata atanr atanmaz pros gramcya e-mail atmak iin ayarlanm olabilir), ve listesindeki kendine c s atanm hatay grr. Herkesin benimPortal listesi, kendine atanan hatas ou lar gstermesi iin ayarlanmtr (buna testi de dahil, unk ona da o c s c c u hatalar atanabilir) 3. Programc hatann detayna tklar, ve tanm okur. Kendi gelitirme ors tamnda hatay tekrar ettirerek (duplicate) kendi de grr, ve tamir etou mek iin kollar svar. c 4. Programc hatay tamir edince, yeni kodu kaynak kontrol sistemine ekler. Projenin teknik lideri her gn banda test makinasna (bkz. 11.3 blm) u s ou u zaten srm yapyordur, ya da acil bir srm yaplarak (o hata ok nemli uu uu c o ise) test makinasna en son kodlar atlr. 5. Programc, portalden tamir edilmi hatann detayna tekrar inerek, bu s sefer bir deiiklik yapar. Hatann konumunu zld olarak deitirir, gs co u u gs ve hatann yeni sahibi olarak testi arkadan seer. Hatay kaydeder. c s c Simdi programc kendi benimHataPortal ekranna dndunde, tamir o ug 360

GELISTIRME ORTAMI etmi olduu hatann kaybolduunu grecektir (ok gzel, yapacak i s g g o c u s azald). 6. Bu hata tabii kaybolmad. Testi kimse, benimHataPortalna girdiinde c g (ya da ayn ekilde e-mail aldnda) portala girecek, ve listesindeki s g hatay grecektir. Testilerin hata almas garip olmamal, testinin grevi o c c o sadece test etmek olduu iin bu hatann onun listesinde olmasnn tek g c bir anlam vardr: Hata tamir edilmitir, ve tekrar test edilmeye hazrdr. s 7. Test makinasnda da en son kodlar olduuna gre, testi arkada bu makig o c s naya balanarak hatann olduu ksma/blme giderek kontroln yapar. g g ou u u 8. Eer hata gerekten tamir olduysa, testi portala dnerek o hatann g c c o detayna gelecek, ve kapand statsne getirecektir. Baka yapmas uu s gereken bir ey yoktur. s 9. Fakat hata hl ortaya kyor ise, o zaman hatann statsn ak aa c uu u c olarak deitirmeli, ve sahibi olarak (tamir ettiini zanneden) programcy gs g atamal, yani, hatay programcya geri gndermelidir! Ve bu ekilde i o s s ak tekrar balam olur. s s s 10. Eer hata tamir olmu ise, kapand statsn alan hata herkezin listesing s uu u den kaybolacak, yani tamir edilen hatalarn arasna karm olacaktr. s s Not: Konu hakknda eklememiz gereken iki nokta yledir: so Dikkat edilmesi gereken bir nokta, bir hatann tamir olmu s ama, o hatadan bamsz baka bir hata ayn ekranda/blmde g s ou bulunmasnda ortaya kar. Bu yeni hatann eski hata uzerc ine not dulmemesi gerekir. Cunk yeni hata deiik bir us u gs hatadr. Ayr ekilde takip edilmesi gerekecektir. s Ustte tarif edilen dzende yle bir nans farki uygulanabilir: u so u Testi hatay atar (programcy seerek). Ama programc, tamirc c den sonra tesiye geri atama yapmaz. Sadece hata konumunu c zld ye getirir. Bu durumda testinin grevi, periyodik co u u c o bir ekilde portal uzerinde stats zld durumunda olan s u u co u u hatalar kontrol etmektir unk hatay geri kendi benimPortal c u listesinde grmeyecektir. o ITracker Evet, genel hatlar ile tarif ettiimiz bu i akn ITracker program ile gerekletirmeye g s s c s alacaz. ITrackerin nasl kurulacan A.9 blmnda bulabilirsiniz. Proc s g g ou u grama admin olarak ilk girdiinizde bu ekran greceksiniz. (Eer bu ekran g o g 361

11. PROJE YONETIMI Ingilizce geldiyse, My Preferences altndan Turkish seerek Trke ekrana gelebilc u c iriz) 2 Yukardaki ekranda, beklenecei gibi, hibir proje yok. Ilk yapmamz gereken, g c o bir proje yaratmak. Ilk nce Sistem Bakm seeneine tklayn. c g Proje Bakm | Bakm Yap seeneinden Proje Listesi ekranna gelin. c g Simdi ust sada bulunan sayfa ikonuna basarak yeni proje yaratma say g fasna gelebilirsiniz. Ustteki rnek bilgileri girerek hemen bir proje yaratmamz mmkn. Proje o u u ismi deneme olarak seildi. c Kullanclar Simdi de kullanclar yaratmamz gerekiyor. Bu kullanclar, projede grev ya o pan programclar, proje mdr gibi kimseler olacaklar. ITracker kullanan u uu herkese ayr bir kullanc ismi gerekecek, unk herkes kendine ait olan sorunc u lari (hatalar) kendi kullancs uzerinden grecek. o Sekil 11.8 uzerinde grldu gibi ilk kullancy yaratyoruz. Kullancnn o u ug ismi Ali, ve testilik grevini yrtecek. Ali, uygulamay test edip kan hatalar c o uu c programclara atamak ile grevli. o
2 ITracker

program bu satrlarn yazar tarafndan T rkeletirilmitir u c s s

Sekil 11.3: 362

GELISTIRME ORTAMI

Sekil 11.4:

Sekil 11.5:

363

11. PROJE YONETIMI

Sekil 11.6:

Sekil 11.7:

364

GELISTIRME ORTAMI Aliyi eklediimiz ekrana dikkat ederseniz, ona birok hak verdiimizi gryoruz. g c g ou Bunlardan en nemlisi Proje Bakm ve Sorunu Kapat haklardr. Proje o mdr (ya da testisi) olarak Ali, sorunlar tamir edildikten sonra tekrar test u uu c edip, sorunun zlp zlmeyeceine karar verebilecek tek kii olmaldr. Proco u u co u g s gramclar sorunlar kapatmamal, Aliye test edilmesi iin yollamaldr. c

Sekil 11.8: Aynen Aliyi yarattmz gibi, Veliyi de benzer ekilde ekleyebiliriz. Tabii g s Velide testilere zel haklar olmayacak. c o Hata Eklemek Bu noktada, Ali ve Veli sistemi kullanmaya hazrlar. Ali testi, Veli programc. c Simdi, Alinin sisteme nasl sorun eklediini grelim. g o Ali, ilk giri yaptnda benimITracker ekrann grecek. Buradan, ust ksmdaki s g o Proje Listesi seeneinden deneme projesini grebilir. Ali, en solda bulunan c g o ul ikon gurubundan ortadakini seerek, yeni bir sorun ekleyecek ve Veliye c u c atayacak. Grelim. o Atanma yapldktan sonra, grmek iin Veli olarak sisteme girebilirsiniz. o c Sekil 11.11 uzerinde grldgu gibi bir sorun Veliye atanm. o u u s Not: Eer Veli, benimITrackernda kan listesini, sadece ona atanm g c s sorunlara indirmek istiyorsa, bunun ayarn rahatlkla yapabilir. En ustteki Tercihlerim seeneinden, c g 365

11. PROJE YONETIMI

Sekil 11.9:

Sekil 11.10:

366

KULANIM KILAVUZU benimITracker Blmlerimi Sakla ksmna gidip, orada Atanm Sorunou s lar hari btn dier listeleri kapatabilir. c uu g Simdi gelelim i akmzda nemli bir blme: Veli, uygulama kodlarn s s o ou hatasn tamir etmek uzere deitirdi, kendi gelitirme makinasnda test etti gs s ve tamir edildiine karar kld. Simdi, bu hatann tekrar test iin Aliye geri g c gnderilmesi gerekiyor. o Hata listesinden bu hatay deitirmeyi seip, aadaki gibi bir giri yags c s g s parsa, hatay Aliye geri gndermi olacaktr (krmz ile iaretli alanlardan) o s s Bu sayede Ali, kendi benimITracker sayfasndan, tamirini istedii hatann g geri gelmi olduunu grecek, bu hatay test ederek eer tamir olmusa Kas g o g s pat seenei ile hatay kapatacaktr. Kapanm statsndeki hatalar kimsenin c g s uu benimITracker listesinde gzkmezler. Onlar tamir edilmitir! o u s

11.4

Kullanm Klavuzu

Kullanm klavuzu (turnover document) belgesi, bir projeyi gelitirmi pros s gramclar projeden ktktan sonra, onlardan sonra kod uzerinde bakm yapc mas gerekecek programclara braklm bir mesaj niteliini tar. Bu dokmanda s g s u uygulamaya yeni bir kod paras eklemek iin yaplmas gerekenler, gelitirme c c s ortamnn nasl kullanlaca, en son kodu sonu ortamna gndermek iin g c o c yaplmas gerekenler gibi bakm/idare detaylar anlatlr.

Sekil 11.11: 367

11. PROJE YONETIMI Kullanm klavuzu, danman irketlerinin her proje sonunda urettii stans s g dart dkmanlardan biridir, unk proje bittikten sonra takm elemanlar genelde o u c u baka projelerde ve baka mteriler iin grevlendirilirler, ve bu orijinal takm s s us c o projeden ayrlaca iin onlarn tm bilgilerinin bir yerde belgelenmesi arttr. g c u s Fakat kullanm klavuzu, irket ii (in-house) yazlm takmlar, ya da urn s c u irketleri iin bile faydaldr. Takma yeni katlan programclar bu belgeleri s c kullanarak gelitirme srecine daha rahat bir ekilde dahil olabilirler. s u s Web uygulamalar dnyasnda, eer uygulamay iletmekle ve ayakta tutu g s makla sorumlu bir ASP (Application Service Provider - Uygulama Servis Salaycs) g irketi var ise, kullanm klavuzunun sonu ortam ile alkal blm en ok ons c a ou c lara hitaben yazlacaktr. Sonuta uygulamay srekli iletmekle grevli olanc u s o lar onlardr, ve sonu ortam blm servis nasl balatlr, veri tabanna c ou u s balanmak iin gerekenler, sonu ortamna kod gnderme gibi detaylar g c c o ierdii iin ASPler iin okunmas gereken blmler hline gelirler. c g c c ou a Teknik lider kullanm klavuzu belgesinin en nemli yazardr, unk siso c u temsel detaylara hkim olan kii o olacaktr. Fakat bazen bu grev, kariyeri a s o teknik liderlik ynnde ilerleyen senior bir programcya da verilebilir. o u

Sekil 11.12: 368

Ekler

369

Ek A

Aralar c

B
ya da

u kitapta anlatlan kavramlar evde uygulayabilmeniz iin, baz proc gramlarn kurulmas gerekiyor. Bu programlar srasyla javac derleyicisi, java yorumlaycs, Ant derleme sistemi, JBoss Uygulama Servisidir. Gelitirme arac olarak Emacs editr ve IDE ortam anlatlacaktr, fakat s ou herkes kendi ortamn kullanabilir, rnekler hibir IDEye bal deildir. Bu o c g g programlarn hepsinin nasl kurulacan ve kullanlacan bu blmde anlatg g ou acaz. g Kitapta referans edilen tm rnek kodlar ve aralar u o c
http://sourceforge.net/project/showfiles.php?group_id=135492

http://www.mycompany.com/kurumsaljava

adresinden bulunabilir.

A.1

Ornek Kodlar

Projede referans edilen rnek kodlar kurmak ve iletmek ustteki balantdan o s g kitap-code-xx.xx.zip dosyasn indirin ve an. Dosyann alm hli, aadaki c c s a s g gibi olacaktr.
+- DistObjs | +- EJB | | +- CarsEJB | | +- CounterStateful | +- JMS | | +- CarsJms | | +- Filtered

371

A. Araclar
| | +- SimpleListenerServer | | +- SimpleMdbServer | +- RMI | | +- CarsRMI +- Hibernate | +- HibernateComposite | +- HibernateManyToMany | +- HibernateQueries | +- HibernateRelFetchSelect | +- HibernateSimpleRelations | +- SimpleHibernate +- ProfileSample +- Struts | +- StrutsHibAdv | +- StrutsHibLogin | +- StrutsHibPerformance | +- StrutsHibSimple | +- StrutsHibTags | +- StrutsTiles | +- StrutsUpload +- lib | +- commons | | +- commons-beanutils.jar | | +- commons-collections.jar | | ... | +- hibernate | | +- c3p0-0.8.4.5.jar | | +- classes12.zip | | +- ehcache-1.1.jar | | +- hibernate3.jar | ... | +- web | | +- jstl.jar | | +- struts.jar +- tools +- README.english +- README.turkce +- build.xml +- clean.sh +- lgpl.txt

Projelerin hepsi ust dizin lib altndaki jar dosyalarn kullanmaktadrlar. Pr Hibernate iin gereken jarlar lib/hibernate, pr Web/Struts/JSTL odakl u c u jarlar lib/web ve Apache Commons jarlarna ihtiya duyan projeler, lib/ c commons dizinleri altndan Ant derleme sistemi tarafndan alnp kullanlr. HEr projenin derlenmesi o projenin altndaki build.xml aracl ile yaplmaktadr. g Hibernate uzerinden veri taban etkileimi gerektiren her proje ./resources/ s 372

Ornek Kodlar hibernate.cfg.xml dosyasnda tanml veri tabanna gitmek uzere ayarlanmtr. s Bu veri taban uzerinde gereken emay her proje iinde mevcut (ve tekilerden s c o deiik olabilecek) ./src/sql/tables_mysql.sql dosyas iinde bulabilirsiniz. gs c

A.1.1

Hibernate

Pr Hibernate ile alkal rnek kodlar Hibernate ust dizini altndaki projelu a o erde bulacaksnz. Bu kodlar yanlzca komut satrndan ileyebilecek ekilde s s hazrlanmtr; Hibir grsel birim mevcut deildir. Her Hibernate projesi ant s c o g komutu ile derlenebilir ve JUnit birim testleri ant test ile iletilebilir. Birim s testleri, hibernate.cfg.xml uzerinde tanml olan tabana gitmek uzere ayarlanmtr. s

A.1.2

Web

Struts ust dizini altndaki her proje bir Web uygulamasdr. Counluu JSP/JSTL/Strut g g s/Hibernate teknolojisini kullanr. Web projelerini JBoss uzerinde deploy etmek iin build.properties iindeki JBoss dizinini tanmlamamz gerekiyor. Ornek c c bir build.properties aada gzkmektedir. s g o u Liste A.1: build.properties
project.title=Jakarta Struts Blank project.distname=kitapdemo project.version=1.1 doc.src=./WEB-INF/src/java jboss.home=c:/devprogs/jboss-4.0.1 distpath.project=\${jboss.home}/server/default/deploy

Bu tanmlardan, kendi zel JBossumuz iin deimesi gereken jboss o c gs .home deikenidir. Bu deikenin programcnn kendi makinasnda kugs gs rulmu olan JBossun yerini gstermesi gerekir. s o distpath.project, SAR paketinin hangi dizine gideceini gsterir. g o project.distname, JBoss altnda gidece SAR paketinin ismini oluturacak s baz kelimedir. Tm rneklerde bu kitapdemo kelimesidir, yni Web prou o a jeleri iin SAR dosyasnn ismi kitapdemo.sar olacaktr. c Web projemizi derlemek iin gelitirme dizininde c s
\$ ant

komutunu kullanrz. Birim testleri iletmek iin ise s c


\$ ant test

yeterlidir. 373

A. Araclar

A.1.3

Datk Nesneler g

JMS, EJB, RMI teknolojilerini kullanan datk nesne mimari rnekleri, DistOg o bjs dizini altnda bulunabilir. Her ana teknolojinin rnekleri DistObjs altnda o alt dizinler olarak bulunacaktr. Her datk teknoloji rnek dizini iinde, datk teknolojiyi kullanan bir g o c g Web projesi de mevcut olacaktr. Bu projenin yapabildikleri (functionality) StrutsHibAdv projesi ile ayndr. Sadece, tm Hibernate eriim kodlar ikinci u s bir servis katman uzerinde, ve datk nesne teknolojisi uzerinden eriilerek g s yaplmaktadr. O zaman DistObjs altndaki Web kodlarn test ederken, servis tarafnda bir deil, iki JBoss JVMi balatmamz gerekiyor. g s Iki JBoss demek, iki gelitirme projesi demektir. DistObjs altndaki Web s projelerinin dizinlerine girerseniz, en ust seviyede Server ve Webclient dizin lerine ayrlm olduunu greceksiniz. Bu iki proje, iki deiik JBoss deploy s g o gs dizinine gitmesi gereken iki deiik projedir. Hangi projenin hangi JBossa gs gideceini ayarlamak iin build.properties dosyasnda gerekli deiiklii yag c gs g pabilirsiniz. Ayn makinada iki JBoss balatmak iin gerekli deiiklikleri A.4.2 s c gs blmnde anlatlmaktadr. ou u Her iki projeyi bir kerede derlemek iin, teknoloji dizinin (JMS, EJB, RMI) c altnda bir build.xml bulacaksnz. Bu build.xmlin amac, nce Server dizini, o sonra Webclient dizinine teker teker girip iki kere ant komutu vermekten kurtulmaktr. Bylece bir ust seviyeden tek ant ile iimizi halletmi oluyoruz. o s s Ayrca, Server projesindeki POJO tanmlarnn WebClienta gnderilmesi iin o c bir kopyalama ilemi gerekir, bunun iin Server dizinindeki derleme, Webs c Client derlemesinden nce yaplmaldr; Ust seviyedeki build.xml bu sray o hatrlayacak ekilde hazrlanmtr. s s

A.2

Java

Java derleyicisini (javac) ve yorumlaycsn (java) kurmak iin, http:// c java.sun.com/j2se/1.4.2/download.html sitesine girin ve J2SE 1.4.2 (ya da en son) srm tklayn. Tercihen iinde NetBeans program dahil edilmemi uu u c s olan paketi kurmanz daha iyi olacaktr. Windows Windows iin sonu exe ile biten kurulu programn aln. Indirim bitince exe c s dosyasna tklayn, ve ynlendirici (wizard) ekranlarn takip edin. JDKyi nero eye kurmak istediiniz size sorulacaktr. g Unix Indirmi olduunuz j2sdk-1_4_2_08-linux-i586.bin adndaki bir dosyay, s g komut satrndan root ya da yeterli haklar olan bir kullanc altndan 374

Ant
\$ j2sdk-1_4_2_08-linux-i586.bin

eklinde iletin. Bu dosya, kendi kendini aan (self inating executable) trnden s s c uu bir iler dosyadr, yni bir tr zip dosyasdr. Dosya alnca, j2sdk-1_4_2 s a u c _08-linux-i586 adnda yeni bir dizin greceksiniz. Bu dizini alp, herhangi o bir dier dizine (genelde /usr/local/) altna koyarsanz, Java kurulu ilemini g s s gerekletirmi olursunuz. c s s

A.3

Ant

Ant, Java iin vazgeilmez derleme sistemidir. Herhangi bir grsel IDEnin c c o salayabilecei derlemeden ok daha gl ek zellikler tar. Ant ile her trl derg g c uc u o s u u leme ve alkal ek ileri yerine getirebiliriz. a s Mesela Ant, shellden komut arma, dosya ve dizin kopyalama, jar oluturma c g s gibi birok zellii build.xml iinden kullanamanza izin verir. Bunlar nec o g c den yaplmtr? Cunk bir derleme sreci, yanlzca .java dosyalarn .class s u u dosyalarna evirmekten ibaret deildir. Baz ayar dosyalarnn bir yerden tekine c g o kopyalanmas, baz dizinlerin silinmesi (mesel JBoss altndan) ve bir XYZ a programnn arlmas gerekebilir. Tm bunlar derleme dilimiz iinde ihtiya c g u c c olduka yapabiliyor durumda olmalyz. c

A.3.1

Kurmak

Antin kurulu programn http://ant.apache.org/bindownload.cgi adresins den indirebilirsiniz. Indirdiiniz dosya, bir zip ya da tar.gz dosyas olacaktr. g Bu dosyay Anti kurmak istediiniz dizin uzerinde an. Biz gelitirme ortam g c s olarak c:/devprogs adl bir dizin altnda tm gelitirme odakl programlar u s koyuyoruz. Zipin almas bittikten sonra, mesela c:/devprogs/apache-ant-1.6 gibi c bir dizin yaratlm olur. Komut satrndan ant komutunu uygulayabilmek iin, s c c:/devprogs/apache-ant-1.6/bin dizininin sistem PATHine eklenmi olmas s gerekiyor. Bunun iin Windowsda Control Panel | System | Advanced c | Environment Variables listesindeki PATH deikenine Antin bin dizinini gs vermeniz gerekiyor. Sekil A.1 uzerinde bu ilemi gryoruz. s ou Ayn ekilde, JAVA_HOME deikeninin de ayn panelden sisteme bildirilmesi s gs gerekiyor. JAVA_HOME iin JDKnin kurulmu olduu dizini veriniz. Java kuc s g ruluu iin A.2 blmne baknz. s c ou u

A.3.2

Kullanmak

Ant ile bir projeyi derlemek istiyorsanz, o projenin (genelde en ust) dizini iinde build.xml adnda bir dosya bulmanz gerekir. Bu dosya iinde Ant iin c c c lazm olan tm derleme komutlar mevcuttur. Derleme ilemini balatmak iin u s s c
ant

375

A. Araclar

Sekil A.1: Ant Dizinini PATHe Eklemek

komutunu, build.xmlin olduu ayn dizinden balatrsanz, Ant otomatik olarak g s o dizindeki build.xml dosyasn kullanacan bilecektir. Onu okur ve iindeki g c derleme ilemlerini balatr. s s Eer gelitirme srasnda herhangi bir sebebten tr komut satrndan (cd g s ouu ile) daha alt dizinlere indiyseniz, ant komutunun alt dizinden balayp ust s dizinlere karak en yakndaki build.xmli bulup iletmesi iin, ant -find c s c komutunu kullanabilirsiniz. Derleme komutlarmz, ismi build.xml olmayan bir dosyada tutmak istersek (bu pek nadir yaplr), o zaman, mesel my-build.xml adnda bir dosya a iin, c
ant -f ./my-build.xml

komutunu kullanabiliriz.

A.3.3

Build.xml

Ant kullanmak, build.xml iinde Ant taskleri kullanarak targetler yaratmak c demektir. Task, daha nceden yazlm ve etiketi salanm Ant komutudur. o s g s Mesel Java kodu derlemek iin kullanlan javac bir Ant taskidir. Bu task, a c ismi tipik olarak compile olan bir target iinde kullanmak gerekir. c 376

Ant Bir targeti, komut satrndan ismini belirterek direk arabiliriz. c g Bir target, build.xml iindeki dier bir targeti arabilir, ya da bir tarc g c g get tekine dayanyor (depends) olabilir; O zaman dayanlan target, ilk o arlan target iletilmeden nce iletilecektir. c g s o s Balang s c Her build.xml, <project> etiketi ile balar. s
<project name="blank" basedir="." default="all"> ... </project>

Burada proje ismi bir tanmdan ibarettir, basedir projenin ana dizininin neresi olduunu belirtir (. iinde bulunan dizin demektir), ve default ise Ant g c iletilirken target belirtilmezse, hangi targetin farz edilmesinin gerektiini (des g fault) belirtir. Sabit Deerler g
<property file="build.properties"/>

eklinde bir kullanm ile, sabit deikenleri alk olduumuz bir .propers gs s g ties dosyasndan alabiliyoruz. Bu dosya iinde tanmlanan her variable=vsvs c eklindeki deikene, build.xml iinden \${variable} eklinde eriebiliriz. s gs c s s Classpath javac ve java Ant tasklerine bir CLASSPATH gerekir (ayen komut satrnda java ve javacnin ayn bilgilere ihtiya duyduu gibi). c g Ayrca, ayn classpath, hem derleme hem iletmek amal gerektii iin, tek s c g c bir kez tanmlanmas faydaldr. Bu tanm merkeziletirmek iin <path> etiketi s c kullanlr.
<path id="compile.classpath"> <pathelement location ="build/WEB-INF/classes"/> <pathelement location="\{jboss.home}/lib/jboss-jmx.jar"/> <fileset dir="lib"> <include name="**/*.jar"/> <include name="**/*.zip"/> </fileset> .... </path>

Bir <path> tanmlarken, hem jar, hem de direk dizin ismi kullanlabilir. Ayrca bir dizin altnda belli isim dzenine uyan bir dosya grubu da kullanlabilir. Bu u <fileset> taski ile baarlmtr. s s Tanm yapldktan sonra, bu dizin, dosya topluluuna sadece compile. g classpath ismi ile referans edilebilecektir. 377

A. Araclar Derlemek Derlemek iin (mesel compile adnda bir target iinde) javac taski yle c a c so kullanlr.
<target name="compile" depends="prepare,resources"> <javac srcdir="src/java" destdir="./build/classes" debug="true"> <classpath refid="compile.classpath"/> </javac> </target>

srcdir, tm Java kaynaklarnn balad ust dizini belirtmektedir. Ant, u s g buradan balayarak tm alt dizinlerdeki tm .java dosyalarn bularak s u u derleme ilemini yapacaktr. s destdir ise, sonu dosyalar olan .class dosyalarnn nereye konulacan c g belirtir. debug ise, bir Exception atldnda bu hata iinde hatann hangi Java g c satrndan geldii bilgisinin hataya dahil edilip edilmemesini kontrol eder. g Gelitirme srasnda bu seenein true olmasn iddetle tavsiye ediyoruz. s c g s <classpath refid> ise, daha nce tanmladmz classpath dizini, sadece o g ismini kullanarak referans ederek kullanmaktadr. s Bir Java Class Iletmek Bir Java programn armak iin komut satrnda iletilecek Java classn c g c s paketiyle beraber ismi, ve bulunabilecei bir CLASSPATH yeterli olurdu (tabii g bir de Java classnn iinde bir main() metotu gerekir). Bu ii Ant ile yapmak c s istiyorsak, yle bir kullanm gerekir. so
<target name="xxx" depends="clean,compile"> <java fork="yes" classname="org.mycompany.kitapdemo.vs.MyClass" taskname="xxx" failonerror="true"> <classpath refid="compile.classpath"/> </java> </target>

fork, Java srecinin aran srecin paras olup olmayacan kontrol u c g u c g eder. classname paket ismiyle beraber class ismini alr. failonerror hata olursa durulup durulmayacadr. g 378

Ant Burada en ilgin gelecek kullanm, ilk kez bir dayanma (depends) ilikisinin c s gsterilmesidir. Bu targetin tanmna gre, depends="clean, compile" ile o o xxx targeti ilemeden nce clean ve compile targetlerinin ilemesi art konulmutur. s o s s s Bu da normldir, bir classi iletmeden nce derleme yapmak isteriz. a s o Ant, ayrca sadece deien dosyalar derlemeyi bilecek kadar aklldr. Yni, gs a eer bir nceki derleme ile o an arasnda hi Java dosyas deitirmediyseniz, g o c gs derleme ileme hibir ey yapmadan geri dnecektir. s c s o Komut Satrna Ckma Ant, normlde shell uzerinden arabileceiniz her komutu, build.xml iinden a c g g c arabilir. Bunun iin <exec> taski kullanlr. c g c
<exec executable="command"> <arg line="-filan"/> <arg line="param1"/> <arg line="-falan"/> <arg line="param2"/> </exec>

Bu komut, eer komut satrnda verilseydi, yle gzkecekti: g so o u


\$ command -filan param1 -falan param2

Dosyay Dosyaya Kopyalamak Bir dosyay dier bir dosya ismiyle (htta baka bir dizine) kopyalamak iin, g a s c u komut kullanlr. s
<copy overwrite="true" file="./from/directory/myFileName.txt" tofile="./to/directory/otherFileName.txt"/>

Dosyay Dizine Kopyalamak Bir dosyay dier bir dizine ayn isimle kopyalamak iin, u komut kullanlr. g c s
<copy overwrite="true" file="./from/directory/myFileName.txt" toDir="./to/directory"/>

Birok Dosyalar Kopyalamak c Bunun iin, classpath tekniinden tandk gelebilecek <fileset> kavramn kulc g lanyoruz. 379

A. Araclar
<copy todir="/to/dir" includeEmptyDirs="yes"> <fileset dir="src"> <patternset> <include name="**/*.xml"/> </patternset> </fileset> </copy>

Bu komutla, build.xmlin olduu dizinin altndaki src dizini iindeki, her .xml g c ile biten dosya, dizin yapsyla beraber, /to/dir adl dizine postalanacaktr. Dizin Silmek ve Yaratmak Dizin silmek iin (dir isminde bir dizin iin mesel) c c a
<delete dir="dir"/>

eklemek iin ise, c


<mkdir dir="dir"/>

kullanlr.

A.4

JBoss

Kurulmas en rahat uygulamalardan biri herhalde JBosstur. Tek yapmanz gereken, http://www.jboss.com/products/jbossas/downloads adresinden en son JBoss zip dosyasn indirmektir. Kurmak iin unlar yapn. c s Windows Dosyay bir dizinde an. JBossun kurulmu olduu dizine, JBOSS_HOME diyec s g lim. JBoss servisini balatmak iin, JBOSS_HOME/bin/run.bat dosyasna tklarsanz, s c servis balayacaktr. Windows uzerinde JAVA_HOME deikeni tanmlanmi olduu s gs s g iin, daha fazla bir deiiklik yapmanz gerekmemitir. c gs s Linux JBoss kodlar pr Java kodu olduklar iin hem Windows hem de Unix oru c tamnda hi deiiklik gerektirmeden alsabilirler. Indirdiimiz zip dosyasn c gs c g Unixe kopyalayp orada aarsak, JBossu Unix ortamnda hi deiiklik gerekc c gs tirmeden iletebiliriz. Unixte bir zip dosyasn amak iin, unzip komutu kuls c c lanlr. JBoss zipini amak iin c c
unzip jboss-4.0.1.zip

komutunu kullann. Su anda iinde bulunduunuz dizinde jboss-4.0.1 adnda c g bir ek dizin oluturulmu olmas gerekiyor. Bu dizin altnda ./bin/run.conf s s dosyasna girin. Bu dosya iinde c 380

JBoss
#JAVA_HOME="/opt/java/jdk"

eklinde comment edilmi bir satr bulacaksnz. Bu satr comment-out edip, s s JAVA_HOME deikenine A.2 blmnde JDKyi kurmu olduu dizini eitleyin. gs ou u s g s Artk JBossu balatmak iin s c
sh JBOSS_HOME/bin/run.sh

komutunu kullanabilirsiniz.

A.4.1

Deploy Dizinleri

Tabii ilk kurulduu haliyle JBossun iinde sadece rnek uygulamalar mevg c o cuttur. Eer kendi uygulamanz JBossa dahil edip altrtmak istiyorsanz, g c s uygulamanzn nereye gideceini bilmeniz gerekiyor. g Bir JBoss uygulamas, bir WAR, EAR ya da SAR paketleri iinde olabilir. c Bir JBoss paketi, aslnda uygulamann almas iin gereken tm dosyalar c s c u ieren bir dizin ya da bir dosyadr. Eer paketi tek bir dosya olarak grmek c g o istiyorsanz, mesel myapp.ear adnda bir dosya uretebilirsiniz. Bu uretimi her a zaman Ant scriptlerimize yaptrrz, unk belli dosyalarn paket iinde belli c u c dizinler altnda olmas gerekmektedir (J2EE standart bunu belirler) ve Ant bu ilemleri kodlayabileceimiz uygun yerdir. s g Tek bir dosya iinde bir EAR, WAR ya da SAR yapsn koymak, kapal c dosya kullanmdr. Ak dosya kullanm ise, biraz nce paketin iine (bir c o c sktrma program ile) koyduumuz tm dosyalara ve dizinlere hi dokuns g u c madan, ama ayn sonek ile (mesel .ear) olduu gibi bir dizini JBossa gndera g o mektir. Yni myapp.ear dosyas yerine myapp.ear/ gibi bir dizin ismini JBossa a verirsek, JBoss hi bir fark gzetmeden bu dizini de ileme koyacaktr. c o s Tercihimiz hangisi? Biz ak paket eklini tercih ediyoruz. Bunun sebepleri c s iin 3.3 blmndeki anlatma bakabilirsiniz. c ou u Uygulama paketimizi oluturduktan sonra gndermemiz gereken yer, ou s o c g zaman ve gelitirme amal olarak JBOSS_HOME/server/default/deploy dizini s c olacaktr. Bu dizin, JBoss iin zel bir dizindir; JBoss, balar balamaz bu c o s s dizinde ne olup olmadna bakar. Bu dizinde olan ve sonu sar, ear ya da war g ile biten dizinlerin ya da dosyalarn bir kurumsal uygulama olduuna kanaat g getirir, ve onlarn iindeki ayar dosyalarna giderek (J2EE standartna gre c o nerede olduklar bellidir) uygulamanz ileme koyar. s Peki neden JBOSS_HOME/server/default altndaki deploy dizinine baklmaktadr? Baka bir dizin altndaki deploy dizinine baklmaz mi? Bu kesinlikle yaplabilir. s Eer JBossu balatrken komut satrnda g s
bin/run.bat -c newdirectory

gibi bir komut verirseniz, JBoss uygulamalar JBOSS_HOME/server/newdirectory/deploy altnda arayacaktr. Fakat genelde -c seenei ile hibir dizin c g c verilmedii iin JBoss, default dizininin istendiini farz eder ve uygulamalar g c g orada arar. Bu kullanm, kme ile alsmamz gereken ortamlarda deiecektir. u c gs 381

A. Araclar

A.4.2

Gelitirme Amal Port Deitirmek s c gs

Bazen birden fazla kullancnn ortak bir Unix makinasnda gelitirme yaps mas ya da test programlarn iletmesi gerekebilir. Birden fazla gelitiriciyi s s tek bir JBoss kuruluundan desteklemek iin, JBOSS_HOME/server/default s c dizininin bir kopyasn kartarak, mesel JBOSS_HOME/server/user1 gibi bir c a dizin yarabilirsiniz. Ikinci bir kullanic iin JBOSS_HOME/server/user2 olabilir, c vs. Bylece mesel birinci kullanc, kendi JBossunu balatmak iin o a s c
sh run.sh -c user1

komutunu kullanabilir. Fakat iimiz daha bitmedi: Bu dzende eer hibir s u g c deiiklik yaplmazsa ve kullanc tekinden habersiz bir ekilde sh run.sh gs o s ile birden fazla JBoss servisini ayn makine uzerinde altrmaya kalkrsa, c s s ikinci JBossu balatan kullanc, kulland portlarn bakas tarafndan kuls g s lanlmakta olduuna dair bir mesaj grecektir. Bunun sebebi de basittir. g o JBoss iindeki HTTP, RMI, JNDI gibi J2EE servisleri, kendilerini d dnyaya c s u ae etmek bir porta ihtiya duyarlar. sh run.sh kullanan herkes JBOSS s c _HOME/server/default dizinin bir kopyasn kulland iin, o dizin altnda g c tanmlanm ve ayn olan port deerlerini kullanyor olacaktr. Bu sebeple iks g inci servisi balatan kullancnn port akma hatas grmesi ok normldir. s c s o c a Gelitirme ve test amal olarak bu hatadan kurtulmak iin, tarafmzdan s c c JBOSS_HOME/server/default altnda port tanm yapan her dosya kartlp, c port deerlerinin ba tarafna 1den 6ya kadar olan saylar eklenerek, ayr ayr g s dizinlerde yeni ve birbirinden deiik port tanm dosyalar yaratlmtr. gs s Bu yeni tanm dosyalarn almak rnek kodlar ve aralarn adresinden kio c tap-tools-jboss-4.0.1-portlar.zip adl dosyay indirin. Bu dosyay geici c bir dizin altnda an. c
+- jboss-4.0.1-portlar | +- 1-port | | +- conf | | | +- jboss-service.xml | | +- deploy | | | +- jbossweb-tomcat50.sar | | | | +- server.xml | | | | +- jms | | | | | +- uil2-service.xml | +- 2-port | | +- conf | | | +- jboss-service.xml | | +- deploy | | | +- jbossweb-tomcat50.sar | | | | +- server.xml | | | | +- jms | | | | | +- uil2-service.xml ...

382

JBoss Grldu gibi port dizinleri, 1-port ile balayp 6-porta kadar devam edeo u ug s cektir. JBossunuzun hangi port balang deeri ile balamasn istiyorsanz, s c g s o balang deerine ait olan alt dizinin altndaki hereyi olduu gibi aln, s c g s g ve kendi ayr JBoss kuruluunuzun (mese JBOSS_HOME/server/user1) dizini s a altna brakn. Ayn eyi ikinci kullanc user2 altnda yapacaktr. Bylece sh s o run.sh -c user1 ve sh run.sh -c user2 komutlar birbiri ile akmam c s s olur.

A.4.3

K me Ortamnda Port Deitirmek u gs

Kme ortamnda ve yine test amal olarak, eer ayn makinada bir kme u c g u oluturmak istiyorsak, yine port deiiklii yapmamz gerekiyor (kmeler hakknda s gs g u detaylar 5.4.8 blmnde bulabilirsiniz). ou u Ama dikkat: JBoss, bir kme iletebilmek iin gerekli olan ayarlar JBOSS_ u s c HOME/server/default altnda deil, JBOSS_HOME/server/all altnda tutmakg tadr. Eer test hatt sonu ortamnz her makinada bir JBoss JVMi olmak g a c uzere planlanmsa, o zaman her makinada s
sh run.sh -c all

komutunu kullanarak kmenizi balatabilirsiniz. JBoss, iindeki JGroups ktphanesinin u s c uu yardmyla multicast protokolu uzerinden network uzerindeki dier kme bir g u imlerini otomatik olarak bulacaktr. Fakat elinizde tek bir makina var ise, ve bu tek makinada bir kme testi yapu mak istiyorsak, yine port deiiklii yapmamz gerekecek. Ve A.4.2 blmnde gs g ou u anlatlan teknii burada kullanamayz. Ama aslnda kme artlarnda port g u s deitirme ilemi daha da basit olacak. gs s Ayn JBOSS kuruluu altnda (ve ayn makinada) yeni bir kme birimi s u yaratmak iin, JBOSS_HOME/server/all dizinini JBOSS_HOME/server altnda c node1 ve node2 olarak olarak kopyalayalm. Daha sonra mesel node1 altndaki a /conf/jboss-service.xml dosyasna girelim, ve burada ports kelimesini arayalm. Su ekilde bir kod tanmn bulacaksnz: s
<!-| ... <mbean code="org.jboss.services.binding.ServiceBindingManager" name="jboss.system:service=ServiceBindingManager"> <attribute name="ServerName">ports-01</attribute> <attribute name="StoreURL"> ../docs/examples/binding-manager/sample-bindings.xml </attribute> <attribute name="StoreFactoryClassName"> org.jboss.services.binding.XMLServicesStoreFactory </attribute> </mbean> -->

383

A. Araclar Bu tanm parasnnn, <! ve --> iaretleri ile sarlm olduuna dikkat edelim; c s s g XML tanmlarnda bu iaretler comment iin kullanlr, yni ustte grdumz s c a o ug u tanm, aslnda iptal edilmi bir tanmdr. Kme ortamnda port deiiklii iin, s u gs g c bu tanm nce aktif hle getirmemiz gerekiyor. Eer <! ve --> iaretlerini o a g s doru yerlere koyarsak, yni ustteki tanm g a
<!-| ... --> <mbean code="org.jboss.services.binding.ServiceBindingManager" name="jboss.system:service=ServiceBindingManager"> <attribute name="ServerName">ports-01</attribute> <attribute name="StoreURL"> ../docs/examples/binding-manager/sample-bindings.xml </attribute> <attribute name="StoreFactoryClassName"> org.jboss.services.binding.XMLServicesStoreFactory </attribute> </mbean>

durumuna getirirsek, o zaman tanm aktif hle gelmi olur (sadece --> iaretini a s s alttan, tanm bloununun ustne tam olmakla) ve JBossumuz ports-01 g u s s kimlikli port tanmn kullanmaya balar. ports-01, ustte belirtilen ../docs s /examples/binding-manager/sample-bindings.xml dosyasndaki bir kimlik deeridir. g Ikinci kme birimi iinse, JBOSS_HOME/server/node2 altndaki /conf/ u c jboss-service.xml dosyasna girip, ayn comment deiikliini yapp, bu segs g fer ports-01 yerine ports-02 kullanmamz gerekecektir. Bu son deiiklii gs g yapmakla, sh run.sh -c node1 ve sh run.sh -c node2 ile balatlacak s JBosslarn birbirleri ile akmas engellenmi olur. c s s

A.5

Linux

Ornek programlar kodlarken onlar iletebilmek iin bir servis ortamna ihtiyacmz s c vard: Test makinamzda Linux iletim sistemini kullandk. Istanbul Mecidiyekyde s o mbSan irketinde toplattrdmz Intel bazl, network ve grak kart ana kart s g uzerinde dahil olan ve 1 GB hafza, 2 Ghz ilemci, 40 GB disk kapasitesine s sahip olan bir servis makinasnda Suse Linux kuruldu (bu donanma 600 YTL denmitir). o s Dizst gelitirme bilgisayarndan kod gnderimi, ve ssh ile sisteme gireu u s o bilmek iin, makinay yerel bir aa dahil etmek gerekti. Bunun iin her iki c g c bilgisayar bir huba baland (bir RJ-45 kablosu ile iki bilgisayar arasnda dig rek kablo ekilmesi bir ie yaramayacaktr). Linux kurulumu, paketten kt c s c g hliyle networke hazrdr, fakat buna ek olarak servis makinasna bir IP adresi a verilmesi gerekecek. En basit yntem olarak bir statik bir IP vermek iin Etho c 384

Cygwin ernet kart eth0 iin (eer tek kart var ise) /etc/sysconfig/network/ifcfgc g eth0 dosyasnda
STARTMODE="onboot" BOOTPROTO="static" BROADCAST="10.10.255.255" IPADDR="10.10.11.184" NETMASK="255.255.0.0"

tanmlar yaparsanz bilgisayarnz baladnda yeni bir IP adresi olacaktr. s g Bu ayarlara gre, bilgisayarnzn IP adresi 10.10.11.184 olarak seilmitir. o c s Bundan sonra eer bu makinay grmek istiyorsanz, dizst bilgisayarnza g o u u ayn alandan (10.10.11. ile balayan) bir IP adresi verebiliriz. Bundan sonra s telnet ve ssh ile Linux makinanz eriilebilir hle gelecektir. s a Linuxu reboot etmek iin, root olarak c
\$ shutdown -r now

komutunu, sadece durdurmak iin c


\$ shutdown -h now

komutlarn kullanabilirsiniz. Seenek -r reboot, -h ise halt kelimeleri iin birer c c ksaltmadr.

A.6

Cygwin

Cygwin programn kurmak iin, http://www.cygwin.com sitesini ziyaret edec lim. Ilk sayfa yklendikten sonra, Sekil A.6 uzerinde gzken sa taraftaki u o u g Install Cygwin Now ikonu uzerine tklamamz gerekiyor. Bunun sonucunda bize setup.exe programn indireceimiz bir yer sorulacaktr. Bir yer seelim, g c ve program indirildikten sonra uzerinde tklayarak kurulu ilemini balatalm. s s s Kuruluun ilk ekrannda hemen Next tuuna basabiliriz. Bundan sonra, s s kan ul seenekten Install from Internet seeneini seelim. Root Dic c u c c g c rectory olarak c:/cygwin dizinini seebiliriz. Tekrar Next tuundan sonra, c s kurulu dosyalarn nereye koyacan soracaktr. Burada c:/installs gibi bir s g dizin ismi verebiliriz. Select Your Internet Connection seenei ile, kurulu c g s ileminin Internete nasl balacan tanmlyoruz. Direct Connection uyguns g g dur. Sekil A.3 uzerinde gsterilen bir sonraki ekran, Cygwinin hangi siteden o indirileceini sorar. g Bir sonraki ekran, Cygwinin indirilecebilecei mevcut sitelerin bir listesidir. g Buradan bir site ismini seebiliriz, ve Next tuuna basarz. Bu aamada, kodc s s larn indirilecei siteden mevcut paketlerin bir listesi alnacaktr. Bu ykleme g u aamas 10-15 saniye srebilir. Cevap gelince, kurulacak Cygwin paketlerin liss u tesi alttaki Sekil A.4 uzerindeki gibi gzkecektir. o u Dikkat: Next tuuna basp kuruluu balatmadan nce, bir ilem daha yaps s s o s mamz gerekiyor. En son listede bize lazm olacak tm programlarn hepsi halen u 385

A. Araclar

Sekil A.2: Cygwin Sitesi

Sekil A.3:

386

Cygwin

Sekil A.4:

Sekil A.5:

seilmi deildir. Bu seimi yapmak iin, en ustteki All yazsnn yanndaki yuc s g c c varlak iaretinin uzerinde sadece bir kez tklamamz gerekiyor. Bunu yaptktan s sonra bekleyin, ve ekran Sekil A.5 uzerinde grlen hle dnecek. ou a o us Grdumz gibi Default yazlar Install yazlarna dnt. Artk bir o ug u o us u 387

A. Araclar daha Next tuuna bastnzda, Cygwin altndaki tm paketler kurulmaya balanacaktr. s g u s Bu kurulu aamas ok uzun zaman srebilir! Tavsiyemiz, bu kurulu ilemini s s c u s s makinann baka bir ii olmad zaman yapmanzdr. Fakat Cygwin paketinin s s g tm bekleyiinize deen bir paket olduunu sylememiz gerekiyor; Ne de olsa u s g g o Windows uzerinde Unix komut satrna ve komutlarna sahip olmak, yabana atlr bir avantaj deildir. g

A.7

MySQL Front

MySQL-Front, MySQL veri taban iin en popler nyzlerden biridir. Bu proc u o u gram kullanarak veri tabanlarn grebilir, sorgu yapabilir, grsel olarak tablo, o o kolon ekleyebilir ve bir tablo iindeki veri satrlarnn (belli bir limit dahilinde) c listesini grebilirsiniz. o Program indirmek iin http://www.mysqlfront.de/download.html adresinc den en son srm aln. Kurulmas, standart bir Windows program gibidir ve uu u olduka basittir. c

A.8

OpenSSH

ssh ve scp programlarn kurmay, sadece Windows ortam ve Cygwin (A.6) kurulmad artlar iin anlatacaz unk eer gelitirme ortamnz Linux ise g s c g c u g s ssh zaten iletim sisteminde kurulmu olarak gelecektir. Solaris ortamnda ise s s eer ssh yoksa (ounlukla vardr) makinadan sorumlu admine bu program g c g kurdurtabilirsiniz. Hatt Windows ortamnda da, eer Cygwin kurmusanz a g s ssh, Cygwin paketinin iinden kullanma hazr bir hlde kacaktr. c a c Windowsda sshi ve scp programlarn kurmak iin, nce http://sshwinc o dows.sourceforge.net/download/ adresinden Binary Installer Releasei indirin. Kurulu programn balatn ve sadece Client iin kuruluu sein. Kus s c s c rulum yaptnz makina, uzerinde gelitirme yaptnz makina olduu iin, g s g g c sadece kod gndermekle ykml olacaktr, bu yzden bir ssh mterisi (client) o u u u u us olmas yeterlidir. Kurulu ekranlarn takip edin, istediiniz bir kurulu dizini sein, ve kus g s c ruluu tamamlayn. Simdi yeni atnz bir komut satr ekranndan ssh ya da s c g scp komutlarn iletebilirsiniz. s

A.9

ITracker

http://sourceforge.net/project/showfiles.php?group_id=54141

adresinden Download balantsn takip ederek oradan itracker_xxx.express g .zip dosyasn bulup indirin. Bu zip tamamen kendi kendine yeterli (selfcontained) bir JBoss da iermektedir, yni hazrlklar tamamlandktan sonra c a 388

ITracker tek yapmanz mesel ITRACKER dizini altndaki kurulumu ITRACKER/jboss- a 3.2.5/bin altndaki run.bat ya da run.sh ile balatmaktr. s o Ilk nce ITrackern verilerini tutacak MySQLde alan yeni bir veri tac s banna ihtiyacmz var. Bu veri tabannn ismi itracker olsun. Veri tabann MySQLFront (A.7) ile yaratabiliriz. Taban hazr olunca, taban doru tablog larla doldurmak iin ITRACKER/sql/mysql/install altndaki create_itracker c _core.sql ve create_mysql_user.sql dosyalarn iletmemiz gerekecektir. s Bunlardan sonra, JBoss ITrackern veri tabanndan haberdar olmas iin, c JBoss uzerinde ITrackerDS adnda bir J2EE veri kayna (data source) yarat g mamz lazm. Bunun iin bildiimiz gibi deploy dizini altnda sonu -ds.xml c g ile biten bir dosya yeterli oluyor. Biz ITracker iin itracker-ds.xml adnda c bir dosya yarattk. Bu rnek dosyay kitap kodlar altndaki conf dizininde o bulabilirsiniz. Ayrca ITRACKER/jboss-3.2.5/server/default/deploy/it- hsqldb-ds.xml adndaki dosyay silin, unk paketten kt haliyle ITracker c u c g HSQLDB kullanmak uzere ayarlanmtr. ITrackerDSin tanmn altta veriy s oruz.
<?xml version="1.0" encoding="UTF-8"?> <datasources> <local-tx-datasource> <jndi-name>ITrackerDS</jndi-name> <connection-url> jdbc:mysql://localhost:3306/itracker </connection-url> <driver-class>org.gjt.mm.mysql.Driver</driver-class> <user-name>root</user-name> <password></password> <exception-sorter-class-name> org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter </exception-sorter-class-name> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources>

Son bir basamak, MySQL iin JDBC srcs (driver) jar dosyasn JBossa c uu uu vermek, bu da yine kitap kodlar altnda bulabileceiniz lib/hibernate/ g mysql-connector-java-3.1.11-bin.jar dosyasn ITRACKER/jboss-3.2.5 /server/default/lib dizini altna atmaktr. Artk localhost:8080/itracker adresinden program kullanmaya balayabilirsiniz. s Program otomatik olarak ilk kullancy yaratyor, kullanc: admin, ifre: admin s ile programa girip projeniz iin gerekli bilgileri girmeye balayabilirsiniz. c s ITracker resmi srm, Trkeletirilmitir durumdadr. Kullanc olarak uu u u c s s sisteme girdikten sonra, Tercihlerim (My Preferences) seenei altndan Trke c g u c dilini seerek uygulamann dilini tamamen deitirmeniz mmkndr. c gs u u u 389

A. Araclar

A.10

Linux Uzerinde CVS

CVSi kurmak iin ncelikle c o


ftp://ftp.gnu.org/gnu/non-gnu/cvs/

adresinden en son cvs kaynak srmn indirin. Bu dizin altnda bugn iin uu u u u c en son srm cvs-1.11.tar.gz dosyasdr. Bu dosyay Unix makinanza kopyuu alayp tar xvzf ile aabilirsiniz. Alan yeni dizin iinde c c c
./configure make make install

komutlarn srasyla uygulayn. Bu komutlar CVS iler kodlarn gerekli yerlere s koyacaktr. CVS servisini balatabilmek iin cvs adnda bir kullanc ve cvs adnda bir s c grup yaratmanz gerekiyor. Su komutlar srasyla uygulayn.
groupadd cvs mkdir /home/cvs chgrp cvs /home/cvs useradd cvs -d /home/cvs -g cvs chown cvs /home/cvs

Bu satrlar ile cvs Unix grubu altnda olan bir cvs kullancs yarattk. Bunlar yaptktan sonra /etc/inetd.conf dosyas iine u satrlar eklemelisiniz. c s
cvspserver stream tcp nowait root /usr/bin/cvs cvs --allow-root=/home/cvs pserver

Ek olarak /etc/services dosyas iinde u satrlarn olmasna dikkat etmeliyiz: c s


cvspserver 2401/tcp

Artk inetd servisini tekrar balatrsak (killall -HUP inetd), yeni ayarlar s devreye girmi olacaktr. Eer Unix sistemimiz xinetd kullanyorsa, ek bir s g aama olarak /etc/xinet.d/cvspserver dosyasna unlar yazmalyz s s
service cvspserver { socket_type = stream wait = no user = cvs group = cvs env = HOME=/home/cvs # Fixes RHL 7.0 problem! server = /usr/bin/cvs server_args = -f --allow-root=/home/cvs pserver

390

Linux Uzerinde CVS


disable } = no

Bu ayarlar xinitd ile devreye sokmak iin, root kullancsndan c


/etc/init.d/xinetd restart

komutunu armalyz. Bunlar yapldktan sonra, sisteme yeni bir CVS kulc g lanc eklemek, o kullancy yeni cvs Unix grubuna eklemek kadar basittir. Bunu
/usr/sbin/usermod -G cvs user123

szdizimini kullanarak yapabiliriz. o

A.10.1

Kullanmak

CVSe balanan sistemler iin baz ayarlamalar gerecektir. Her CVS kullancs, g c ncelikle hangi havuzda ilem yapacan belirtmelidir. cvs -d havuz_ismi o s g seenei ile bunu rahata yapabiliriz, ya da CVSROOT evre degikeninde havuz c g c c s ismini tanmlayabiliriz; Bylece srekli -d kullanlmasna gerek kalmaz.Eer o u g kod havuzu yerel ise (ayn makina uzerinde yani), o zaman
export CVSROOT=/tmp/deneme1

kullanlabilir. Fakat havuz ile kullanc ayr sistemlerde ise (ki genelde byle o olur), o zaman
export CVSROOT=:pserver:remoteuser@hostname:/tmp/deneme1

Simdi bu ayarlar kullanarak CVSe giri yapabiliriz. s


cvs login

Cevap olarak alttaki kt gelecektir. c


(Logging in to hostname) CVS password: ...

Sifrenizi girdikten sonra, cvs co MODULE komutunu kullanarak (MODULE yerine kendi kod havuz ismimizi koymay unutmayalm) depolanm kodlar kendi s yerel diskimize alabiliriz. Kodlar yerel dizine geldikten sonra, istediimiz dosyada deiliklik yapg gs makta serbestiz. Yaptmz deiikliklerden tatmin olduysak, o zaman kodu g gs geri koyabiliriz. En ust dizin seviyesinden,
cvs commit

komutunu verince, bu komut en batan balayp her alt dizini ziyaret ederek s s orada bulduu deiiklikleri havuza gnderecektir. g gs o Eer biz bakalarnn yapt deiiklikleri grmek istiyorsak, yine en ust g s g gs o seviyeden, 391

A. Araclar
cvs up -d

komutunu verebiliriz. Bu komut bizim dokunmadmz dosyalarn en son hlini g a alacak, fakat hem bizim hem de baka bir programcnn yapt deiiklikleri s g gs birletirim (auto-merge) bize sunacaktr. Bu dosyalarn hangileri olduu bize s g ekrandan bildirilecektir. Eer cvs commit komutunu gnderdiimizde gncelleme akmas var ise, g o g u c s cvs commit hata verip geri dner. Bunun anlam, yukarda gsterildii gibi o o g cvs up -d ile auto-merge yaparak akmalar zmeye mecbur olduumuz c s co g anlamna gelir. Cakma Ornei s g Programclar, projenin son hlini almak ve kendileri kodlamaya balamak iin a s c depodan dosyalar kendi ortamlarna indirirler. Dosya uzerinde ekleme, karma c s iini kendi ortamlarnda yaparlar. Ileri bitince KKI sistemine geri verirler. s sistemi, eer ayn anda iki kiinin deistirdii bir dosya varolduunu buKKI g s g g g lursa, deiim arpmas olduunu haber verir. Bu haber ayn dosyay ikinci gs c s g geri veren programcya gsterilir. Byle bir durumda programcnn, deimi o o gs s dosyay depodan kartp, kendi srm ile birletirmesi (merge) gerekir. CVS c uu u s program iimizi rahatlatmak iin otomatik bir birletirici sunmaktadr. s c s s Mesel, BeniDegistir.c dosyasin iki kii ayn anda deitirmitir. Ileri a s gs s bittikten sonra, belli aralar ile u ilem yapmslardr; s s
cvs commit BeniDegistir.c

Bu komutu veren ikinci programc bir hata mesaj grecektir, ve depo ikinci o srm kabul etmeyecektir. Cunk ikinci deiiklikten nce bakas dosyay uu u u gs o s deitirmi, ve ikinci kii eklememimizi ondan bir nceki srme gre yapmtr. gs s s o uu o s CVS unu demeye almaktadr; Bir de kodun son haline bir bakn, eer s c s g deiikliiniz hala geerliyse, bana birinci deiiklikle beraber tekrar geri vergs g c gs meniz gerekiyor. Eski deiikliin uzerinde yazp onu kaybetmek istemiyorum. gs g Bu durumda, en yeni (birinci deiiklikten sonraki) srm depodan alp, kendi gs uu u dosyamz ile birletirmemiz gerekecektir. Dikkat edelim, bu birletirme hala s s merkezi depoda deil, bizim ahsi dosyamzda olacaktr. g s
cvs -q co -P BeniDegistir.c

Bu komuttan sonra, elinizde yle bir kayt gececek.. so


#include <stdlib.h> #include <stdio.h> int main(int argc, char **argv) { init_arayici(); ara();

392

Linux Uzerinde CVS


if (argc != 1) { fprintf(stderr, "tc: Hic Oge Gondermeye Gerek Yok.\\n"); exit(1); } if (nerr == 0) KodYarat(); else fprintf(stderr, "Kod Yaratilmadi.\\n"); <<<<<<< BeniDegistir.c exit(nerr == 0 ? CIKIS_BASARILI : CIKIS_BASARISIZ); ======= exit(!!nerr); >>>>>>> 1.6 }

Karakterler <<<<<<< ve ======= arasna gelen satrlar, bizim eklememiz. ==== === ve >>>>>>> 1.6 arasna gelenler depoda bizden nce yaplan deiikliklerdir. o gs Bu birlemi dosyaya bakarak, bizim eklememizin geerli olup olmadna baks s c g malyz, ve dosyay son haline getirmeliyiz. Bunu yaparken ==== iaretlerini s kartartmamz gerekecektir, ve teki deiiklii yapan programcya deiiklikleri c o gs g gs hakknda soru sormamz gerekebilir. Bundan sonra, en son formu bulup, u kos mutu tekrar iletmemiz gerekecektir. s
cvs commit BeniDegistir.c

Fakat artk cvs komutu baaryla tamamlanacak. Depoda artk gncel dosyanz s u bulunuyor!

A.10.2

CVS ve Binary Dosyalar

CVSte en sk karlanan problemlerden biri, gif, jpg ve jar gibi ikisel (bis nary) dosyalar CVSe ekleyip, geri alnca bu dosyalarn bozulduunu grmekg o tir. Bunun sebebi, CVSin bu dosyalar metin bazl dosyalar gibi grmesi ve o uzerinde deiim yaparken dosyay bozmasdr. gs Bu hatay dzetlmek iin, CVSi kurduunuz makine ve dizine girip u u c g s deiiklii yapn. CVS_DIZIN/CVSROOT/cvswrappers adl bir dosya bulacaksnz. gs g Metin bazl dosyadan daha deiik muamele grmesini istediiniz dosyalar, u gs o g s ekilde cvswrappers iine ekleyin. s c
*.gif -k b *.jpg -k b *.jar -k b ..

Bu yeterli olacaktr. CVSi tekrar balatmanza bile gerek yoktur. Simdi yeni s ekleyeceiniz dosyalar doru muamele ediliyor olacaklar. Eer daha nceden ekg g g o lenmi dosyalar dzeltmek istiyorsanz, cvs remove, cvs commit ve arkasndan s u cvs add ve cvs commit ile bu dosyalarn dzgn hlini tekrar ekleyin. u u a 393

A. Araclar

A.11

Enscript

Kod gzden geirmek iin en rahat yol, kodu yazcdan basmak, ve uzero c c ine yorumlar yazarak kodu bu ekilde gzden geirmektir. Kod gzden geirme s o c o c (code review) toplantlar iin kodu kada basmak, ayrca nem tamaktadr. c g o s Kodu gzden geirilen programc da toplant srasnda kendisine verilen yorumo c lar, dzeltmeleri kendi yazc kts uzerine yazarsa, kendi iin yararl olacaktr. u c c Yazcdan alnacak ktdaki kodlarn 2 kod sayfas bir yazc sayfasna c gelecek, ve her satrn numaral olacak ekilde alnmas en iyisidir. Bu sayede, s kod gzden geirme toplants srasnda ..u, ve u hata, u nolu satrda gibi o c s s s szler sylenebilecektir. Bu trden bir ktnn alnmas iin kullanlan program, o o u c c enscript programdr. Enscripti Windowsda kurmak iin kitap kodlarmz kitap-tools-enscript c .zip dosyasn atktan sonra en ust dizin enscript dizinini olduu gibi alp c g c: seviyesine kopyalayn. Bu kopyalama ileminden sonra PATH deieninize s gs c:/enscript dizinini ekleyebilirsiniz. Cygwini A.6 blmnde anlatld gibi ou u g kurmu olanlar iin hibir ek ileme gerek yok, enscript zaten kurulmu olarak s c c s s gelecektir. Artk komut satrnda herhangi bir yerden enscript komutunu kullanabilirsiniz. 394

Emacs Simdi sra Ghostview ve Ghostscript kurmaya geldi. Postscript dosyalar Unixilerin uzun sredir bildii bir formattr. Enscript program formatlad c u g g kaynak kodlar grsel olarak biimlendirip, kty postscript olarak yazd iin, o c c g c Ghostview adnda bir gsterici programa ihtiyacmz var. o ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/ghostgum/gsv46w32. exe) ve ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/AFPL/gs814/gs8 14w32.exe balantlarndan Windows iin Ghostview ve Ghostscripti indireg c bilirsiniz. Bu kadar! Artk istediiniz kodu gzel basmak iin aadaki ekilde bir g u c s g s komut verebilirsiniz. Enscriptin birok seenei vardr, bunlari enscript - c c g -help ile grenebilirsiniz. En standart kullanm, 2 kod sayfas bir yazc sayo fas, satrlarda numaralar, en bata kod isminin ismi balk olarak ve Java s s szdiziminde nemli olan anahtar kelimelerin (keyword) koyu olarak basld o o g formattr.
enscript -pcikti.ps -r -c -C -2 -j --pretty-print=java -r -v --lines-per-page=90 CLASS.java

A.12

Emacs

Emacs dnyada en ok fazla dili destekleyen editrlerden biridir. Teknik lider u c o olarak iiniz shell scriptlerden Javaya, oradan XMLe oradan da Perle ats lamanz gerektirecei iin, her trl ihtiyacnz karlayabilecek bir editre g c u u s o ihtiyacnz olacak. Kurmak iin http://ftp.gnu.org/gnu/windows/emacs/latest/ adresinc den Emacsin son versiyonun indirin. Bu zip dosyasn bir dizinde an (windows c uzerinde genellikle c:/ Unixde genellikle /usr/local/ ). Kurduunuz dizinin g yerine EMACS_DIR olarak referans edersek, Windowsda kuruluu tamamlamak s iin EMACS_DIR/bin/addpm.exe dosyasna ift tklamanz gerekmektedir. c c Bizim kullandmz ayarlar kullanmak/almak iin, kitap kodlarmz arasnda g c bulunan kitap-tools-emacs-xxx.zip dosyasn indirin ve Windowsda c:/ uzerinde an. Bu alm, c:/ altna baz .el dosyalar ve c:/emacs-21.4 dizini c c altna bir takm ek dosyalar brakacaktr. Bizim kullandmz Java gelitirme g s ortam ve bir sredir toplam olduumuz, beendiimiz ayarlar bu dosyalar u s g g g iindedir. c

A.12.1
Modlar

Emacs Ozellikleri

Emacs, her dosya iin belli bir mod aabilir. Modlar o anda edit etmekte c c olduunuz dil iin zel baz yetenekler salarlar. O dile zel girintilendirme g c o g o (indentation), anahtar kelime renklendirmesi (syntax coloring), yardmc tular s 395

A. Araclar bu yardmlardan bazlardr. Hangi dosya iin hangi mod kullanlmas gerektii c g _emacs.el iinde tanmlanabilir. c
(setq auto-mode-alist (append (("\\.C\$" . c++-mode) ("\\.xml\$" . nxml-mode) ("\\.java" . jde-mode)

Grldu gibi Emasc XML dosyalarn sonek .xml sayesinde anlamaktadr, o u ug ve bu dosyalar nxml-mode amaktadr. c Her mod kendi dili iin girintileme (indentation) yapabilir. Indent iin istediiniz c c g blgeyi mouse ile sein, ve MyJDE | Indent, ya da \C-x\= tularn kullann. o c s Ayrca herhangi bir satr uzerindeyken (satrn neresinde olursanz olun) TABe basarak girintileme yapabilirsiniz. Bu zellik ou editrde mevcut deildir. o c g o g M- sembol, Emacs dnyasnda Escape tuu olarak bilinir. Yerine ALT tuu u u s s bask tutularak ta kullanlabilir. Dosya amak iin File | Open File, ya da \C-x\C-f, kaydetmek iin File c c c | Save, ya da \C-x\C-s kullanlr. Dired Dizin gezmek iin Dired modu kullanlabilir. Dired kelimesi, Directory editor c kelimelerinden gelir. File | Open Directory ya da \C-x\d <ENTER> ile girebilirsiniz. Dired size o anki dizinin listesini verir. Bu listede Aa yukar gitmek iin n ve p tularn s g c s Dosyaya girmek iin f tuunu c s Ya da mouse ile dosyaya iaret ederek sol dmeyi s ug kullanabilirsiniz. Eer Diredde bakmakta olduumuz dizin uzerinden bir Exg g plorer penceresi amak istiyorsak, bunun iin MyJDE | Open Explorer In c c Current Dir men seeneini kullanabiliriz (ya da F10 tuu). Ayn ekilde u c g s s MyJDE | Open Cmd In Current Dir Direddeki dizinde bir komut satr (shell) aacaktr. c JDE Cok kuvvetli bir Java modudur. Herhangi bir .java dosyasna girdiiniz anda g aktif olur. Projenizin en ust seviyesinde prj.el varsa, size daha yardmc ola caktr. prj.el yle gzkebilir; so o u
(custom-set-variables (jde-built-class-path (quote ("./lib/hibernate3.jar" ... )))

396

Emacs
(jde-complete-function (quote jde-complete-menu)) (jde-global-classpath (quote ("./lib/hibernate3.jar" .... ))) (jde-sourcepath (quote ("./src/java" )) ) )

Ustteki ayarlar uzerinden, bir metotu aranlar bulmak iin F4, MyJDE c g c | Call Tree (Usage), ile uzerindeyken bir class tanmna gitmek iin F3, s c c MyJDE | Goto kullanlr. Bir class otomatik import etmek iin, classn uzerine gidip MyJDE | Imc port Class, ya da \M-uv kullanabilirsiniz. Bir referansn metotlarn listelemek iin, noktadan sonra F7 ya da MyJDE | Complete kullanlabilir. c Tm bu Java yardmclar, prj.el iinde jarlarn koyduunuz dosyalar ve u c g dizinler uzerinde alr. c s Derlemek Bizim ayarlarmz kurduysanz, MyJDE | Compile ya da \C-x\c, otomatik olarak ant -emacs -find komutunu iletecektir. Ckt, Emacs tarafndan taranr. s Hatalara gitmek iin \C-x\~. Ya da hatann ustne gidip \C-c\C-c kullanc u abilirsiniz. Kopyalama, Yaptrma, Silme s Kopyalama iin \C-c c Yaptrma iin \C-y s c Geri tek karakter silmek iin \C-k c Satr silmek iin \C-t c Hareket Tular s Yukar: \C-p Aa: \C-n s g Sola: \C-j Saa: \C-l g Kelime saa: \C-d g Kelime sola: \C-w 397

A. Araclar Kelime sola silmek: \C-f Belli bir satra gitmek: \C-x\g Buerlar Emacsde her dosya bir buer iinde tutulur. Buerlar arasnda gezinmek iin c c Buffers men seeneinden (ya da \C-x\C-b ile) ya da CTRL art sol mouse u c g dmesine tklayarak tm mevcut buerlar grebilirsiniz ug u o

A.12.2

Emacs ve CTRL tuu s

Emacsde CTRL tuu ok kullanlr. Normal klavyelerde, CTRL ok eriilmez s c c s bir yerde olduu iin zm CAPS LOCK tuunu CTRLa evirmektir. Alttaki g c co u s c kodu ctrl.reg olarak kaydedip, ve uzerine ift tklarsanz, bilgisayar kapatp c atktan sonra CAPS LOCK tuunun CTRL tuuna dnm olduunu grec s s o us us g o ceksiniz.
REGEDIT4 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout] "Scancode Map"=hex:00,00,00,00,00,00,00,00,02,00,00,00,1d,00,3a,00,00,\ 00,00,00

Not: \ iareti satrn bitmediini gstermek iin bizim tarafmzdan koyulmutur, s g o c s norml dosyann iine bu karakteri koymaya gerek yoktur. a c

A.12.3

Ayar Deiiklikleri gs

Ayar deiiklikleri iin _emacs.el dosyasn istediiniz gibi deitirebilirsiniz. gs c g gs Sonra \C-x\C-b ile derleyin ya da \M-x byte-me LISP komutunu iletin. Yeni s deiiklikler annda etkili olacaktr. gs Deiik renkler kullanmak istiyorsanz, _emacs.el ile ayn seviyede olan gs _colors-public.el dosyasnda gereken deiiklikleri yapabilirsiniz. gs

A.13

Cygwin Uzerinde X Windows

Cygwin/X kurmadan nce Cygwini kurmu olmanz gerekecektir. Eer bu kuo s g rulumu yaptysanz, http://x.cygwin.com/ adresinden Install Cywgin/ X Now balantsn tklayn. Bir setup.exe program ortaya kacaktr, bunu g c sabit diskinizde bir yere kaydedin. Bu programn uzerine tklayp, Nexte basn, ve Install from Internet seimini yapn. Cywgin Root Directory olarak Cygc wininizin nerede olduu alglacacaktr, eer alglanmadysa doru dizin yerini g g g siz girin. Sonra iki kere Next ile kurulumu yapn. Herey doru kurulduktan sonra, komut satrndan s g
startx

398

Kaynak Kod Yamalar ile X altyapnz balatabilirsiniz. Bu altyap baladktan sonra, bir (zerinde X s s u servisi ileyen) bir Unix makinasna balanp, X programlarnn ktsn kendi s g c makinanza alabilirsiniz.

A.14

Kaynak Kod Yamalar

Bazlar, ak kaynak kltrnn baarsn her projenin kodunun eriilebilir c u uu u s s (okunabilir) olmasndan hareketle, ayn zamanda kodun herkes tarafndan CVS deposunda deitirilebilir olmas olduunu zanneder. Halbuki, birok aktif ak gs g c c yazlm destekilerinin ounun bir projeye hibir zaman CVS commit hakk olc c g c mamtr1 . Peki o zaman ak yazlmda testilerin fazlal ve hata onarmnn s c c g abukluu nasl mmkn olmaktadr, ve bu ne demektir? c g u u Burada kritik teknoloji, yama (patch) teknolojisidir. Bir yama dosyas, en basit anlatmyla, bir text dosyasdr. Bu dosya, programc yamay oluturacak s komutu verdikten sonra, kod gelitirme dizininde programcnn yapt deiiklikler s g gs ile kodun eski, deimemi hli arasndaki farklarn toplamdr. Bu deiiklikler, gs s a gs bir ya da daha fazla dosya uzerinde dalm olabilir; Yama dosyas bunun tak g s ibini doru bir ekilde yapacaktr. g s Yama dosyas, text bazl bir dosya olduu iin, bir foruma aslabilir, e-mail g c ile baka bir programcya gnderilebilir, istenilen ortamda saklanabilir. Eer bu s o g yamay baka bir programcya alp kullanmak isterse, bu programc, kendi kod s baz uzerinde yamay uygular (applying the patch) ve bylece deiiklikler, o gs onun kod baznda da aktif hle gelir. Bu uygulama ileminin gzel taraf, a s u uygulamay yapan programcnn nceden kendi yapt (farkl) deiiklikleri o g gs bile olsa, yamadaki deiikliklerin ounlukla baaryla uygulanabilmesidir, gs c g s unk deiikliklerin hangi dosyada olduu yama kartma tarafndan kaydedilmitir, c u g s g c s tek potansiyel problem ayn dosya uzerinde iki taraf ta deiiklik yapmsa or gs s taya kar; Fakat bu artlarda akmalar bir birletirim (merge) ile zlebilir. c s c s s co u Yama karmak iin diff, yama uygulamak iin patch komutu kullanlr. c c c Yama kartmak iin kodun ncesinin bilinmesi gerekir; Bu nce kod baz, c c o o ya bir CVSe anonymous eriim uzerinden, ya da programcnn sabit diskinde s mevcut bir kod dizini uzerinden eriilebilir. Genellikle uygulanan yntem CVS s o uzerindendir (fakat CVS yoksa, bir alternatif olduunu bilmek iyidir). g Ak yazlm projelerinde yamalar, genelde nce kullanc ve programc mailc o ing listlerine aslr, ya da, projenin herkese ak olan hata takip sistemine ekc lenir. Bu hataya eklenti (attachement) olarak tamiri gerekletirecek olan yama c s dosyas da eklenir. Ak yazlm projesinin CVSe commit hakk olan ekirdek gelitiricileri, c c s srekli bu hata takip sistemini takip ediyor olurlar. Bylece en son girilen hatay u o farkeden ekirdek gruptan bir programc, yamay hemen kendi kod bazna uyguc layp hakikaten bir hatay iyi edip etmediini kontrol edecektir. Eer hata g g hakikaten dzeltilmise, testi yapan programc yamadan gelen deiiklikleri u s gs
1 http://www.opensymphony.com/oscache/contribute.action

399

A. Araclar CVSe ekler (bunu yapmaya hakk vardr), ve arkasndan hata takip sistemindeki hatay kapatr.

A.14.1

Yama Uretmek

CVS uzerinden yama uretmek iin, projenin en ust seviyesinden c


cvs -q diff -u > /tmp/patchfile.patch

eklinde bir komut kullanlabilir. Eer CVS eriimi yoksa, u komut kullanlr. s g s s
diff -rup /path/to/unmodified/source /path/to/modified/source > /path/to/patchfile.patch.

Yeni dosyalar yamaya eklemek iin ise: c


diff -u /dev/null MyCoolNewFile.java >> /path/to/patchfile.patch

A.14.2

Yama Uygulamak

Yamay uygulamak iin, CVSten en son kod alndktan sonra, projemizin en c ust seviyesinden patch komutunu u ekilde kullanmalyz. s s
patch -Np1 < /path/to/patchfile.patch

Eer missing header for unled di at line 8 of patch gibi hatalar geliyorsa, g u da denenebilir. s
patch -Np0 < /path/to/patch.diff

400

Ek B

D zenli Ifadeler u

Dzenli ifadeler (regular expressions), bir metin iinde belli bir dzene uyan u c u bir kelime dizisini bulmak iin kullanlr. Teknik olarak bu ilemin sonucundan c s bazen u ekilde bahsedilir: xyz dzenli ifadesi abc ifadesine uydu (matched). s s u Ifade, aslnda bir kelime dizisini temsil eden genelci bir beyandr; Aslnda komut satrndan bir dzenli ifadeyi srekli kullanyoruz. * iareti. Bu iareti u u s s bir listeleme komutu ile beraber kullandmzda, * iareti ne olursa olsun g s dzenli ifadesi olduu iin, bu tarife uyan tm dosyalar ve dizinleri geri alm u g c u s oluruz. Fakat dzenli ifade * iaretinden ibaret deildir. Cok daha gcl ve sayesinde u s g u u deiik ve etrel metinler ekip karabileceimiz ifadeler vardr. Ama ondan gs c c c g nce, uzerinde dzenli ifade ileyeceimiz girdi dosyalarn nasl okuyacamz o u s g g grmemiz gerekiyor, yni Perln dosya eriim zelliklerini. o a u s o

B.1

s Perl ile Metin Ileme

Perln metin ileme yeteneklerini bir rnek uzerinde grelim: Perl ile dosya u s o o amak iin open komutu kullanlr. c c
open IN, fileName.txt;

Bu komutla fileName.txt okunmak iin alm olur. Bir dosyay satr satr, ya c c s da tamamen okuyabiliriz. Counlukla (mesel kodda) yaplan metin deiiklikleri g a gs iin dosyann tamamn ayn anda okumak gerekir. Bunu yapmak iin, undef c c \$/; iareti kullanmamz gerekecektir. Bu tanmdan sonra tm dosya ieriini s u c g bir deikene atamak iin, u kullanlr. gs c s
\$fileContent = <IN>;

401

B. DUZENLI IFADELER Bu yapldktan sonra \$fileContent deikeni, dosyadaki tm ierii iinde gs u c g c barndrmaya balar. Kodlamanz daha ksa tutmak istiyorsanz, \$fileCons tent yerine zel bir deiken olan \$_ deikenini de kullanabilirsiniz. Gio gs gs zli deikeni kullanmann iyi taraarndan biri, takip eden tm dzenli ifade gs u u ilemlerinin (eer onlar da deiken belirtmemise) otomatik olarak gizli deiken s g gs s gs uzerinde yaplabilmesidir. Cok basit rnek bir dzenli ifade kullanmak gerekirse o u
open IN, fileName.txt; \$_ = <IN>; s/ahmet/mehmet/sg ; print; close IN;

Bu rnekte, ahmet kelimesini mehmet ile deitirdik, ve ekrana bastk. o gs print komutuna hi parametre vermezseniz, ayn ekilde gizli deiken olan c s gs \$_ kullanldn farz edecektir. g Ilk dzenli ifademiz, hem bulan, hem deitiren bir ifade. Bu ifadenin s/ u gs string1/string2/sg; tabirinde olan string1, aranan ksmdr, string2 ise, aranan ifade bulununca, yerine geecek ksmdr. Deitirmek yerine sadece c gs bulmak istiyorsanz, string1 ifadesini sadece if ile kullanabilirsiniz; if (/ string1/) {.. .} gibi.

B.1.1

Ckt Dosyas

Metin deiimi yapmak iin genellikle deitirilen dosya ikinci bir dizin altnda gs c gs ayn isimde yazlr.
open IN, fileName.txt; open OUT, /tmp/fileName.txt; \$_ = <IN>; s/ahmet/mehmet/sg ; print OUT; close IN; close OUT;

Bu kod parasndaki OUT, deimi ieriimizin gittii dosya olacaktr. Dosyaynn c gs s c g g ayn isimle ald dizinin deiik bir yerde olduuna dikkat edelim. c g gs g

B.1.2

Birok Giri Dosyas c s

Eer bir dizin altndaki birok dosyay ilemek istiyorsak, dosya listesi almak g c s iin <> iaretlerini kullanabiliriz. Bu iaretlerin arasnda, ou iletim sistec s s c g s minden alk olduumuz * kullanm mmkndr. <> kullanmnda geriye bir s g u u u Perl listesi gelecektir, bu listeyi foreach Perl komutu ile gezebiliriz. Mesel a
foreach \$file(<*.java>) { # .. # \$file ile ilemler yap s

402

IFADELER
# .. }

Eer biraz nceki deitirme mantn ustte gsterilen tm dosyalara uygulag o gs g o u mak istersek,
foreach \$file(<*.java>) { open IN, \$file; open OUT, /tmp/\$file; \$_ = <IN>; s/ahmet/mehmet/sg ; print OUT; close IN; close OUT; }

Dosyalarn okunaca dizini deitirmek iin ise, Perl chdir komutu kullanlabilir; g gs c chdir(/vs/vs) gibi.

B.2

Ifadeler

Artk daha zor dzenli ifadeleri gsterebiliriz. Bu yeni daha etrel ifadeleri u o c // arasna yerletirirsek, bu yeni ifadeleri kullanmi oluruz. Bylece o ifadenin s s o temsil ettii metne gre, o anda okunmakta olan dosya uzerinde bu verilen ifade g o uydurulmaya allacaktr. Uydurulan (bulunan) ifade ise, otomatik olarak c s deitirme blmn devreye sokacaktr. gs ou u u Dzenli ifadeler iinde her eit metin dizisi iin, bir komut vardr. Mesel u c c s c a eer 22.33.22, ya d, 33.22.44 yni, genel olarak, iki say, sonra bir nokta, g a a iki say daha, sonra nokta ve son olarak iki say ieren bir dzeni bulmak c u istersek, o zaman tek vermemiz gereken dzenli ifade u olacaktr. u s
/\d{2}\.\d{2}\.\d{2}\./

Burada \d komutu, tek haneli bir sayy temsil etmektedir. Tek karakteri temsil eden tm zel komutlarn listesi Tablo B.1 uzerinde bulunabilir. u o Tablo B.1 komutlar, elle gmeceimiz sabit metin ile ayn ifadenin paras o g c olarak kullanlabilir. Ayrca ou zaman, karakter komutlarn baz zel tekrar c g o etme kurallar ile beraber kullanmak gerekiyor. Bu zel tekrar kurallar, genelo likle, bir dzenli ifade komutunun hemen yanna eklenir, ve yanna eklendii u g tabirin temsil gcn daha da arttrr. Tablo B.2 uzerinde tekrar kurallarn u u u gryoruz. ou Ornekler \$_ = abbbccdaabccdde uzerinde baz dzenli ifade rnekleri grelim1 : u o o
1 Can Uur Ayfer, http://www.mycompany.com/localhost/mycompany/yazi.jsp@dosya= g a_regular_expression.xml.html

403

B. DUZENLI IFADELER

Tablo B.1: Dzenli Ifade Komutlar u Komut \d \D \w \w \s \S \ ^ . \$ Trif a Tek haneli bir say Tek haneli haricinde her ey s Bir alfabe har (a ile z, A ile Z aras, ve _ iareti) s Alfabe haricinde herhangi bir karakter Beyaz boluk (SPACE, s TAB) karakteri Beyaz boluk haricinde hers hangi bir karakter META (ESC) karakteri Satr balang karakteri s c Herhangi bir karakter Satr sonu karakteri

Tablo B.2: Tekrar Komutlar Komut * + ? {n} {n,} {n,m} str1 | str2 Trif a 0 ya da daha fazla 1 ya da daha fazla 1 ya da hi c n kere en az ne kere en az ne kere, ama mden fazla deil g Ya ifade1 ya da ifade2 bulunacak

404

IFADELER /Abc/ Uymaz! \$d iinde hi A yoktur yni Abc bulunamaz. c c a /Abc/i Uyar! Sondaki i ignore case, yani byk-kuk harf ayrm u u uc yaplmasn anlamnda olduu iin Abc ile abc eleir. g c s s /abc/ Uyar! /^abc/ Uymaz! Cunk ^ meta-karakteri dizinin banda anlamndadr u s ve abc alt dizisi \$dnin basinda deildir. g /abc>/ Uymaz! Cunk > meta-karakteri dizinin sonunda anlamndadr u ve abc alt dizisi \$dnin sonunda deildir. g /De>/i Uyar! Dizimizin sonunda de var ve byk-kcuk harf ayrm u u u yaplmayacak! /^ab*c/ Uyar, unk dizinin basinda a ve ardndan sfr veya daha c u fazla b ve ardndan c var! Bu dzenli ifadede olan * karakteri hemen u solundaki karakter iin sfr veya daha fazla kez tekrar eden anlamnda c bir meta karakterdir. /aH*bc/ Uyar! Cunk dizide a ve ardndan sfr veya daha fazla H u ve ardinda bc var! /aH+bc/ Uymaz! Cunk dizide a ve ardndan en az bir tane H ve u onun ardnda bc seklinde bir dzen yok! Bu Duzenli ifadede olan + u karakteri hemen solundaki karakter iin bir veya daha fazla kez tekrar c eden anlamnda bir meta-karakterdir. /a*bc/ Uymaz! Cunk dizinin iinde hi a ve ardndan gelen * yok! u c c Bu rnekte * bir meta-karakter olarak deil; basit anlamyla bir asterisk o g karakteri olarak kullanld iin nndeki ile iaretlenmitir. g c o u s s /a+bc/ Uymaz! Cunk dizinin iinde hi a ve ardindan gelen + yok! u c c Bu rnekte + bir meta-karakter olarak deil; basit anlamyla bir art o g iareti olarak kullanld iin nndeki ile iaretlenmitir. s g c o u s s /a c/ Uymaz! Cunk dizinin iinde hi a ve ardindan gelen yok! u c c /a.*b/ Uyar! Cunk dizide a ve aralarnda bireyler ve sonra b var! u s . (nokta) meta-karakteri herhangi bir karaktere uyar; ardndan gelen * ile birlikte (yni .*) bireyler olarak okunabilir. a s /d.*a/ Uyar! Cunk birey anlamndaki noktann ardndan gelen * u s meta-karakteri sfr veya daha fazla herhangi birey anlamndadr. s /d.+a/ Uyar! Cunk birey anlamndaki noktann ardndan gelen meta u s karakter bir +; Yni bir veya daha fazla herhangi birey a s /da?/ Uyar! Cunk dizide d ve ardndan bir veya sfr tane a gelen u alt dizi var. 405

B. DUZENLI IFADELER

B.3

Gruplama ve Bulunan Kullanmak

Cou deitirme ilemi iin, bulmak iin kullandmz dzenli ifadenin bulduu g gs s c c g u g metnin bir blmn yeni deitirmenin bir paras olarak kullanmamz ou u u gs c gerekebilir. Mesel, alttaki gibi bir kod paras uzerinde a c
import com.sirket.paket.vs; if (bilmemne) soyle boyle; soyle boyle; if (filan) soyle boyle oyle;

yapacamz deiiklik yle olabilir; sadece if komutunu ieren kod satrlar g gs so c (; iareti ile biten kod satrlar, dosya satrlar deil) iinde btn yle byle s g c u u so o ibarelerini, byle yle yapalm. Bu gibi durumlarda, bulunan kelimenin o so kendisi yeni kelimenin bir parasdr, bu yzden bir ekilde onlara eriebilmemiz c u s s gerekir. Bunun iin Perln () gruplama iaretlerini kullanabiliriz. Perlde her c u s dzenli ifade komutu, parantez iine alnabilir. Alnd zaman, ve bu ifade u c g metin paras ile uyutuu zaman (matching), parantez iindeki uyan ksm, c s g c deitirme yapan (ikinci // arasndaki komutlar) ksmda, gruplamann kulgs lanl srasna gre, \$1, \$2, \$3, .. ile eriilebilir. Mesel rneimizde uc tane s o s ao g () kullanm var, birinci uyan ksma erimek iin \$1 kullanacaz. s c g
s/\;(.*?)if (.*?) soyle boyle(.*?)\;/\;\$1if \$2 boyle soyle\$3\;/sg;

406

Kaynaka c
[1] [2] King, G., Bauer, C. Hibernate In Action. Manning Publications, Greenwinch, 2005. Gamma, E., Helm, R., Johnson, R. & Vlissides, J. Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley, Reading Mass., 1995. Meyer, B. Object Oriented Software Construction, Second Edition. Prentice Hall, New Jersey, USA, 1997. Chappel, D., Monson-Haeel, R. Java Message Service. OReilly, Sebastapol CA, 2001. JBoss, Inc. JBoss Admin Development Guide - JBoss 3.2.6. JBoss, Inc., 2004. Burke, B. JBoss Clustering. JBoss Group, Atlanta, GA, 2003. Looseley, C., Douglas, F. High-Performance Client/Server. Wiley Computer Publishing, 1997. Hunt, C. TCP/IP Network Administration. OReilly, 1998 Codd, E. F. A Relational Model for Large Shared Data Banks. CACM, 1:6, 1970 Elmasri, R. Navathe, B. S. Fundemantals of Database Systems, Second Edition. Addision-Wesley, 1994 Brooks, F. P. Jr. The Mythical Man-Month, 1995 Anniversary Edition. Addision-Wesley, 1995 Lewin, R. Complexity, Life at the Edge of Chaos, Second Edition. Phoenix, 2001 Nixon, R. Six Crises. Touchstone Press, New York, 1990 407

[3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]

Kaynakca [14] c Torvalds, L., Diamond, D. Yanlzca Elenmek Iin (Orijinal: Just g For Fun). Bilgi Yaynevi, 2005, Orijinal: Harper Business, New York, 2001

408

You might also like