19 Kasım 2009 Perşembe

Ehliyet sahibi olmak geç olsa da...

Evet ehliyet sınavlarını parlak olmasada geçtim. Artık sürücü ehliyetim var..

Daha fazla kafa şişirmeye gerek yok..

:)

6 Eylül 2009 Pazar

Sürücü kursu; benim de ehliyetim olacak!

Evet artık benim de ehliyetim olacak. Ne ehliyeti mi: tabii ki motorlu vasıta için olanlarından.

Çok şükür yazılmayı başardım. Bakalım hayırlısı...
Eğer bir aksilik olmaz ise 3 aya kalmaz artıkın B sınıfı ehliyet sahibi olacağım.

Neden mi yazdım?

Öylesine...
Okumayı verin sizde...

12 Ağustos 2009 Çarşamba

Sun Java sertifikaları

Sun'ın Java sertifika sınavları Türkiye'de pek yaygın değil. Tabii şu sıralar. Ancak diğer ülkelerde özellikler AB ve ABD'de yaygın imiş.

Bu sertifikalar ne işe yarayacak demeyin. Gerçekte ben de sertifika manyağı bir adam değilim. Sertifikalara da pek itibar etmem. Ancak SCJP, SCJD sertifika konularına bir göz gezdirdim. gerçekten güzel konular var. Öğrenmek için yıllarca piyasada çalışsanız dahi öğrenemeyeceğiniz, denk gelmeyeceğiniz konular mevcut.

Ayrıca bu sertifikaların faydaları da olacaktır. Diğer serifikalara benzer su gibi verilmediğinden, alması biraz zor olduğundan daha kıymetli...

Tecrübeye her daim saygımız mevcut ve mevcut olacak. Ancak bazı durumlarda sertifikalar iyi kullanıldığında, tecrübelerle beraber, hem kişisel hem de maddi faydalarının olacağına inanıyorum. Özellikle de SCJP gibi Sun sertifikalarının.

Bu düşünceler bana iat. Doğal olarakta beni bağlar. Ancak sizlerle de paylaşayım dedim.

Eğer irade gösterebilirsem, düzenli çalışır bir kaç ay içinde SCJP sertifikasını alırsam çok sevindirik olacağım. Bakalım gerçekleri zaman gösterecek.


İyi çalışmalar...

28 Mayıs 2009 Perşembe

Tomcat sunucusu ve saklı bahçe

Bir web sunucum olsun ve bu sunucuda n adet proje - web projesi - çalışmakta olsun. Ancak ben bu projelerime direk erişimi istememekteyim. Bunu bir kaç değişik şekilde yapabilirim.

  • Hiç kod yazmadan TOMCAT sunucusunda HTTP BASIC AUTH özelliğiyle o projeye veya o projenin belli bir bölgesine erişimi kısıtlayabilirim.

Yani http://localhost:8080/TomcatHttpBasicAuth/index.html URL sini çağırdığımda tarayıcımda bir güvenlik ekranı çıkmalı. Kullanıcı adı ve şifremi girince o alana erişebilmeliyim. Buradaki ince nokta; eğer güvenliği geçemez isem kısıtlı bölgemdeki kodlarım asla çalıştırılmayacaktır. Bu güvenlik işlemini Tomcat'in kendisi yapmaktadır.

Bunun için önce Tomcat web suncusunda tomcat_users.xml dosyasına kullanacağımız roller ve kullanıcılar eklemeliyiz. Kullanıcı bilgilerini ve roller - erşiem haklarını - bu xml dosyasında tutmaktadır Tomcat.

Giriş için kullanıcı adı ve şifre sorulma ekranı.

Örnek uygulama ve diğer ayrıntılı ekran görüntüleri için TIKLAYINIZ.

2 Nisan 2009 Perşembe

JPA'da yeni kaydın ID numarasını almak...

JPA ile bir problem çözmeye çalıştığımızı düşünelim. Yeni bir müşteri veya adres defterine yeni bir adres kaydı atmak istiyor olalım. Ve kayıt işleminden hemen sonra kullanılmak üzere bize yeni kaydın ID ( PK ) numarası gerekli olsun.

Bunu diğer yöntemler ile nasıl yapılacağına bir bakalım: Önce kayıt atılır. Sonra veritabanı sunucusu eğer destekliyorsa , örneğin: lastInsertID() gibi bir komutla en son eklenen kaydın ID numarası alınır. Tabi eğer böyle bir komut yok ise ve veritabanı sunucumuz, aletlerimiz transactionı desteklemiyorsa bunun o an eklenen kaydın ID numarası olduğunu ummamız iyimser bir yaklaşım olacaktır. Aynı anda arda arda bir kaç kayıt gelebilir ve elimizdeki ID numarası başka kayıda ait olabilir.

Bunun da çözümleri vardır. Kendi kilit - lock - mekanizmanızı veya veritabanının kilit mekanizmanısını kullanabilirsiniz. Bunun da sakıncalarını, özellikle tablo bazında kilitlemelerin sakıncalarını göreceksiniz. Özellikle bir biri ile dış anahtarlar - FK - ile bağlı tablolara kayıt atarken tablo kitleme bir sonsuz döngüye girebilir. Ve sistem birini feda ederek bu döngüden çıkar. Ama bu işinize yaramaz bir çözümdür.

Ya da kendi kilit mekanizmanızı dolaylı yöntemler ile siz geliştirisiniz. Mesela tablolara birer alan koyarsınız o kayıt kilitli ise o alana bir değer atarsınız. O kayıt ile işlem yapmak isteyenler olursa eriştirmezsiniz böylece...

Tablo kitleme olayı yeni kayıt atarken aldığınız ID numarasının o kayda ait olduğunu garantiler.
Ancak gerekmedikçe tablo kitlememeniz hayrınıza olacaktır. Tablo kitlemeleri sıralara, kuyruklara neden olacağından sistemin performansını düşürür.

Gelelim JPA'da o kaydın ID numarasını nasıl alacağımıza. Öncelikle JPA ORM yazılım iskeletidir. JPA transaction yönetimine sahiptir.


entitymanager.getTransaction().begin();
entitymanager.persist(entitybean);
entitymanager.getTransaction().commit();

int Id = entitybean.getEntityBeanID().intValue();


İşlem bu kadar basittir. Eğer kayıt başarılı ise commit() fonksiyonu veritabanına kayıt işlemini onaylatır. Ve yeni kayıt edilecek olan entitybean nesnesinin ID alanı doğal olarak boştur! Ancak Commit() başarlıysa bu alan JPA tarafından doldurulur. Sizde kolayca bu değeri alırsınız. Ve bilirsiniz ki bu ID kesinlikle o an kaydettiğiniz kayda aittir!

İşte JPA ile hayatınızı kolaylaştıran bir olay daha!!!
Mr. mascule reklamına benzedi biraz ama .... :)

23 Mart 2009 Pazartesi

Url Rewrite Filter ile arama moturu dostu URL yapmak...

Öncelikle arama motoru dostu bağlantılar artık moda olduğundan eninde sonunda karşınıza çıkacaktır. Neden mi? Çünkü MODA!

Peki Java'da bunu nasıl yaparız? Php de bir çok örneği var. Mesela Apache Http sunucusunun mod_rewrite eklentisi ile bunu php , perl v.b. destekli sunucularda yapmak kolay. Hatta php de buna özel betikler var.

Java'da bu soruna merhem olan API ler mevcut. Ben http://urlrewritefilter.googlecode.com adresindeki api kullanarak bir örnek yapacağım. Diğer ulaşılabilir adres ise http://tuckey.org .

Mesela yapmak istediğimiz şunlar olsun :
  • index.jsp yerine /index
  • index.jsp?id=44&baslik=Teneke-adam yerine /index/44/Teneke-adam olsun
yukarıdaki şekilde sitemdeki bağlantıların erişim adresleri arama motoru dostu olmasını çok istemekteyim. Peki bunu nasıl yaparız.

Önce Eclipse'de bir web projesi oluşturun. Bunun /WEB-INF/lib dizini altına urlrewrite-3.2.0.jar'ı ekleyin. Sonrasında ise /WEB-INF/urlrewrite.xml dosyası oluşturun. Adı urlrewrite.xml olan dosya sizin arama motoru dostu bağlantılarınızın kaynağı olacaktır. Sebebi burada geçerli bağlantı dokularını - url pattern - belirteceksiniz. Belirtilen bağlantı dokularına uyan bağlantılar o kurallara göre işletilerek istediğimizi elde edeceğiz.

Bağlantı dokularında dikkat edilmesi gereken bazı noktalar mevcut:

  • from etiketlerinde yazılan bağlantı dokuları ya da regex patternlerde
    ? yerine \?, = yerine \= , & yerine amp; kullanın.
  • Bağlantılarınızı otomatik outboundrule ile oluşturmak için kesinlikle response.encodeURL() kullanın. Örn: response.encodeURL("/index.jsp?id=44&baslik=dayimin-oglu"); gibi. Siz normal yazın ancak response.encodeURL() ile arama motoru dostu url olsun! Ancak unutmayın eğer bağlantı dokusunda - regex pattern - (^/index.jsp\?id\=([0-9]+)amp;baslik\=([0-9][a-zA-Z]+)$) olduğunda siz response.encodeURL("/index.jsp ....") index.jsp'nin önünde "/" işereti olmaz ise aynı dokuya denk değildir! Bunu unutmayın!

Kural örneği resmi:



index.jsp:




Gerisi sizin hayal gücünüze kalmış...

Örnek bir Eclipse projesi : örnek proje

Projeyi indirip baktığınızda daha iyi anlayacaksınız.

22 Mart 2009 Pazar

Php ile değişen alt yapılara ayak uyduran üyelik sistemi yazmak

Php ile değişen alt yapılara ayak uyduracak bir üyelik sistemi yazmak isteyelim mesela.
Bunu nasıl yaparız?

Örneğin sisteme girişlerin denetlemesini bir veritabanından okuyarak yapıyor olalım. Üyeler kullanıcı adlarını ve şifrelerini yazıp sisteme giriyor olsunlar. Her şey buraya kadar normal.

Bir gün patron gelsin ve artık biz o şirketle birleştik ve onların API'lerini kullarak üyelerin girişlerini denetleyeceklerini söyledi. Bu sırada siz kafayı sıyırabilirsiniz gönül rahatlığıyla...

Peki böyle değişken durumlara ayak uyduracak bir sistem yazabilsek ve üye girişlerinin genel yapısı değişmesede, ufacık bir değişiklikle tüm sistem alt yapısı bir anda değişse...

İşte burada sizin üyelik sistemini nasıl tasarladığınıza göre işiniz ya zor ya da kolay olacaktır.

$giris = new UyelikGiris(new BenimGirisAdaptorum("assd", "123"));

if($giris->girisOnaylandiMi()){
echo "Onaylandı\n";
}


Yukarıdaki kodda üyelik sistemi genel yapısı hiç değişmeden sadece Adaptör nesneyi değiştirerek bu işlemi gerçekleyebiliriz. Tüm denetleme yapıları aynı kalır. Sadece "BenimGirisAdaptorum" sınıfı yerine aynı interface'dan türemiş başka bir adaptör nesnesi kullanmamız yeterli olacaktır. Bu sayede üyelik mekanizması şeklen aynı kalacak ancak kullandığı alt yapı esasen değişmiş olacaktır.

Örnek kodlar aşağıda indirilebilir.

Örnek kod: örnek dosya

Örnek kodu incelerseniz herşey kafanızda daha da netleşecektir.

20 Mart 2009 Cuma

Ah filtre vah filtre, amanında web.xml

Evet filtre javada bir nimet olsa gerek. Hele request ve response nesnelerini değiştirme olanığınıyla tanıştıktan sonra acayip bir sevgidir aldı başını gitti içimde...

Neyse yine bir sorunla başlayalım. Sorunlar olmasa hayat çekilmez olurdu herhalde.

Sorun: Daha önce her şeyi ile doğru dürüst çalışan yönetim paneliniz vardır. Daha önce diyorum, çünkü, artık düzgün çalışmıyordur. Eskiden, yönetim paneliniz aracılığıyla girdiğiniz içeriklerde hiçbir sıkıntı olmadığını varsayıyoruz.

Örneğin: Türkçe içerik girdiğinizde hiç bir sorun yaşamıyordunuz. Fakat bir başka işlemi gerçeklemesi için "IkinciFiltre" adında bir filtre yazıyorsunuz. Her şey çok iyi görünürken bir de karşınıza daha önce çözdüğünüz ; Türkçe karekter sorununu ile yine burunburuna kaldınız.

Bu canınızı sıkmıştır. Muhtemelen "IkinciFiltre" her şeyi bozuyordur. Doğrudur. Ancak nasıl? Ve neden?

Burada basitçe filtreler ile alakalı bir kaç şey bilmek lazım herhalde. Filtrelerin ayaklanması ile alakalı işlem adımları aşağıda sırasıya verilmiş

  1. Web.xml'de önce filtreler ayaklanır - initialize -
  2. Ayaklanan filtrelerin önce init() fonksiyonları daha sonra ise bağlantı örüntüsü - url pattern - kimin sorumluluk alanına giriyorsa o filrelerin doFilter() fonksiyonları çalışır.
  3. Web.xml'de girilen sırada, yukarıdan aşağıya çağrılırlar. Eğer bir bağlantı örüntüsü birden fazla filtrenin sorumluluğunda ise web.xml'de hangisi ön sırada tanımlanmışsa onun doFilter() fonksiyonu çağrılır.
  4. Aynı bağlantı örüntüsü sorumluluk alanına giren birden fazla filtre var ise önce ilk tanımlanın doFilter() fonksiyonu çağrılır. Ardından ikinci filtreye birinci filtrenin doFilter() fonksiyonu içinde çağrılan chain.doFilter() fonksiyonuyla geçilir. Sonra n adet filte sırasıyla bu işlemi yapar. Ve zincirin - chain - en altındaki filtre işlemini tamamlarsa yani doFilter() son satırına kadar çalıştırılırsa bu sefer adımların tersinden, n. filtreden ikinciye oradan da birinci filtreye geri dönülür ve en son ilk çalışan filtrenin doFilter() fonksiyonu tamamlanır.
  5. Eğer zincirin en sonunda servlet var ise servlet çalışmasını bitirsikten sonra zincirin en son halkasında olan filtreye görev geri teslim edilir. doFilter() fonksiyonuna tamamlayan en son filtre görevi bir üste ve ... En son ilk çalışan filtre çalışmasını bitirir.
Bu arada servlet bağlantı adresi ile çağrıldığında önce servletin öntanımlı kurucu fonksiyonu çalıştırılır. Ardından servlet ayaklanır - initialize - . Ve ardından filtreler devreye girer. Sonrasında filtre zinciri işlemlerine başlar. Yani yukarıdaki maddeler işleme konulur sırasıyla...

Yukarıda anlatınları daha iyi anlamanıza yardımcı olabilecek bir adet resim aşağıda verilmiştir.




Burada S1, S2, S3 servlettir. F1, F2, F3 filtredir. Okların akış yönü tarayıcının isteğinden - request - sunucuya ve ilgili web bileşenlere doğrudur.

Kaynaklar:
  1. http://java.sun.com/products/servlet/Filters.html
  2. http://www.javaworld.com/javaworld/jw-06-2001/jw-0622-filters.html?page=1

18 Mart 2009 Çarşamba

Bir problemim var "String" ile...

Geçen gün bir hata ayıklama - debug - işlemi sırasında bir String tipinde nesneyi split fonksiyonu ile parçalara ayırdığınızda, bu parçalardan her birinin asıl nesnenin değerinin bir kopyasını da taşıdığını gördüm.

Aslında bunun böyle olduğunu ilk başta anlamadım. :)

İlk aklıma gelen soru şu idi: Alla alla nasıl olurda parçaladığım nesnenin değeri her bir parçanın içinde bulunur ve parçaların değerleri ile value özelliği - attribute - aynı değeri taşımaz?

Yani nesne değeri başka , nesne.value -> String.value <- değeri başka mı ? Nasıl olurda String tipinde bir nesne split fonksiyonuyla n adet parçaya ayrılır ve bu parçalardan her biri olan String tipindeki nesnecikler asıl nesnenin - parçaladığımız nesne - değerini taşır?



Yukarıda bu hata ayıklama işlemini görebilirsiniz.

Sonra şu aklıma geldi: Bir parçadan asıl nesnenin değerine ulaşabilir miyim?
Evet bu fikir takıldı kafama ve uyuyamayacaktım ben de araştırmaya başladım internette...

Bu değeri nasıl alabilirdim? Ve bu değer neden nesnenin parçalarında bulunuyordu?
Sonra Allah'a şükür etmek istiyorum ki; java iyi ki açık kaynak kod - open source -.
OpenJDK'dan java.lang.String nesnesinin kaynak kodunu buldum.

Evet anahtar özellik "private final char value[];". Bu özellik eğer String tipinde bir nesne oluşturulunca değerinin bir kopyası value de tutuluyor olması. :) İşte sorumun cevabına yaklaşma anı! Ancak bu value private :) yani ben nasıl ulaşabilirim bu özelliğin değerine?

Evet onun cevabı da Reflection ...

Aşağıdaki kod parçasıyla bu değeri almayı başardım:


String msg = "*141#3#123455666656564645#";
StringTokenizer st = new StringTokenizer(msg, "*");
String ilk = st.nextToken();
StringTokenizer st2 = new StringTokenizer(ilk, "#");
String ikinci = st2.nextToken();
String ucuncu = st2.nextToken();
String aman = "tamam";

Class t = String.class;
Field f = t.getDeclaredField("value");
f.setAccessible(true);
System.out.println(f.get(ucuncu));
System.out.println(f.get(ikinci));
System.out.println(f.get(ilk));
System.out.println(f.get(msg));
System.out.println(f.get(aman));


Peki bunu başardım ama bu String nesnesini parçaladım bir örüntüye göre - pattern - ancak hepsinde asıl nesnenin değerinin olması biraz pahalı bir işlem değil miydi?

Yani value private final idi...
Her parça aynı nesnenin value özelliğine bir adres ile işaret etmiyorsa - pointer - bu kadar hafızayı boş yere heba etmenin ne anlamı vardı? GC'ye o kadar güveniyorlardı yani?

Yukarıda verdiğim java kodunu çalıştırırsanız enterasan bir sonuç çıkıyor:


System.out çıktıları:

[C@addbf1
[C@addbf1
[C@addbf1
[C@addbf1
[C@42e816

burada farklı olan [C42e816 yani yeni bir String tipinde nesnedir. Diğerleri ise split ile parçlanmış nesnenin parçacık nesneleri ...

Ve aynı özelliği -
value - paylaşıyorlar!

Hem private final bir özellik ve hem de parçalara ayrılmış nesnenin tüm parçacık nesnelerinde aynı tip dolayısıyla aynı değer !

Neyse sonunda bazı şeyleri çözmüş ve rahatlamış olarak uyudum.
Anlamış olmasamda...