29 Nisan 2008 Salı

Tomcat 6

Tomcat 3 kavramı ifade eder.
1) Web sunucusu (EJB container’i yok)
2) Java Servletleri çalıştıran(execute) eden bir uygulama
3) JSP kütüklerini Java Servletlere dönüştüren bir uygulama

Bu anlatımızda Tomcat’in mimarisi ve dizin yapısına temel düzeyde değineceğiz. Tomcat 6, Java SE 5 üzerinde çalışan, Servlet 2.5 ve JSP 2.1 spesifikasyonlarını uygulayan bir uygulama sunucusudur. Servlet ve JSP standartlarını referans almaktadır. Bu ne anlama gelmektedir? Tomcat bu standartları yakınen takip ederek, Tomcat container’i altında çalışan her Servlet/JSP uygulaması, baska bir uygulama sunucusunda da sorunsuz çalışma imkanı verir. Bu ne işimize yarar diye bir soru sorabilirsiniz. Yazımızın girişinde de değindiğimiz gibi Tomcat web sunucusudur yani tam bir uygulama sunucusu değildir, gerekçe olarakta EJB container’in olmaması gösterilmektedir. Ama çok başarılı bir web sunucusudur. Bunu istatiksel örneklerle göstermek yerine tüm küçük ölçekli web uygulamaları veya büyük ölçekli projelerde Tomcat web sunucusunun kullanılması iyi bir örnek olacaktır. Yazılım şirketleri yaptıkları web tabanlı projelerde, projeyi yaptıkları kuruma ya da şirkete, proje teslim edilirken genelde Oracla ya da Jboss uygulama sunucularını kurarlar (bu müşteri isteğidir, daha doğrusu bunlar en başta yazılım veya donanım gereksinimlerinde yazılır) burda değinmek istediğim nokta Yazılım şirketi müşterinin hangi uygulama sunucusunu kullanacağından bağımsız olarak genelde Tomcat i kullanır, nedenleri ise Tomcat in başarılı, performansı iyi, özellikle developer’ların çalışma zamanında developer’larıda yormayacak bir web sunucusudur. Developer uygulamayı geliştirirken web sunucusunu restart etmesi, büyük bir zaman kaybı. Developer’in uygulamayı geliştirdiği makinede Oracle uygulama sunucusunun olduğunu düşünürsek hem makine için hemde developer için tam bir kabus.:)

Tomcat’in Mimarisi ve server.xml
Tomcat bir seri fonksiyonel iyi tasarlanmış bileşenlerden oluşmaktadır. Bu yapı server.xml kütüğünde tanımlanmış. Bu kütükte conf adlı alt dizinde bulunmaktadır.




Blog malesef tag yapısına izin vermemektedir. Yazıyı server.xml kütüğü ile birlikte incelerseniz daha yararlı olacağı kanısındayım.

Context
Context, Tomcat bileşenlerinin en alt bileşenidir ve Containers olarakta adlandır. Tomcat uygulanızı yüklerken(load) standart bir context oluşturmakta ve bunu konfigure etmektedir. Konfigürasyonun bir parçası da uygulamanızın WEB-INF/web.xml’de çalıştırmaktadır.


Connector
Connector TCP portunu ilişkilendiren bileşendir. Uygulama ile istemci arasındaki iletişimi sağlar. Bu iletişimi Tomcat default olarak HTTP portunu kullanarak sağlamaktadır. Bu da 8080 portudur. Uygulamanın URL’i http://localhost:8080/ diye adlandırılır. Bu portun 8080 olması zorunlu değildir, bunu değiştirebiliriz. Örneğin; port =”8090” yazarak.


Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" /
ConnectionTimeout’a set edilen 20000 değeri, session’nın 5 saat 33 dak 20 sn sonra sonlandırılacak anlamına gelmesidir.

Host
Host container’i sanal bir host sunmaktadır. Aynı sunucuda birden fazla host tanımlanabilir.

Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false"
/Host


unpackWARs =”true”, eğer WAR kütüğünü appBase dizininden silerseniz, Tomcat otomatik olarak kütüğü normal dizinine bırakır. Eğer bu false olursa uygulama direk olarak WAR kütüğünden çalıştırılacak yani çalışma zamanında daha yavaş çalışacak çünkü çalışma zamanında unzip edecek.
autoDeploy = “true” eğer uygulamayı Tomcat’in çalışma zamanında appBase dizininden silerseniz, tomcat uygulamayı otomatik deploy eder.

Engine
Container’in üst seviyesidir.Birden fazla host içerebilir ama başka bileşenin container’nı içeremez.

Engine name="Catalina" defaultHost="localhost"
Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/
Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false"
/Host
/Engine



Default Tomcat konfigürasyonu Cataline engine’ni içermektedir, default host’u ise localhost’tur.

Service
Service bileşenin amacı belirli bir engine bir ya da birden fazla connector ile ilişkilendirmek. Default Tomcat konfigürasyonu, tıpkı Cataline engine gibi, Catalina servisini içermektedir.
Service name="Catalina"


Server
Server tüm bileşenlerin üst bileşenidir. Bu bileşen bir ya da birden fazla servis içerebilir.

Listener
Listener bir Java nesnesidir. org.apache.catalina.LifecycleListener interface’ni implement etmektir. Dört tane listener’imiz var.
Birincisi Apache Portable Runtime kütüphanesini aktifleştirmektedir.
İkincisi JSP engine’i aktifleştirmektedir yani update edilen JSP kütüklerini tekrar derler(recompile).
Üçüncüsü JMX(Java Management Extensions) aktifleştirmektedir yani sistem nesnelerini yönetmeyi, remote monitoring olaylarını mümkün kılmaktadır.
Dördüncüsü global kaynakları aktifleştirmektedir yani JNDI kullanarak MySQL vb. veritabanlarına erişmeyi sağlar.

Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on"
Listener className="org.apache.catalina.core.JasperListener"
Listener className= "org.apache.catalina.mbeans.ServerLifecycleListener"
Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"




Giulio Zambon ile Micheal Sekler, Beginning JSP, JSF and Tomcat Web Development kitabından alıntı yapılmıştır.

24 Nisan 2008 Perşembe

AspectJ’ ye kısa bir giriş...

AspectJ nedir? AspectJ’yi anlamak için öncelikle AOP modelini açıklamak lazım. AOP’un kısaltmasıyla başlayalım, Aspect Oriented Programming, Hacettepe Üniversitesi Bilgisayar Mühendisliğindeki arkadaşımız “Cepheye Yönelik Programlama” veya “İlgiye Yönelik Programlama” olarak çevirmiş ama bu anlatımızda kısaca AOP olarak değineceğiz. AOP, uygulamayı nesneler yerine concerns’lere (kesitlere) ayrıştırmaktadır. Java gerçek nesneye yönelik proğramlama dili ve bununla birlikte AOP tekniğini destekleyen en iyi proğramlama dilidir. AspectJ, AOP mantığını taşıyan bir Java gerçekleştirimidir.
Şimdi terimleri açıklayalım

1) Join Points (Birleşim Noktaları)
2) PointCuts (Birleşim Nokta Kümeleri)
3) Advice (Tavsiye Yordam)

AspectJ, join points kavramını aşağıdaki durumların gerçekleşmesi durumunda kullanır.
1 ) Metodu ya da yapılandırıcısını(constructor) çağırdığımız zaman.
2 ) Metodu ya da yapılandırıcısını(constructor) uyguladığımız (execute) zaman.
3 ) Herhangi bir alana (field) erişmek istedigimizde ya da güncellemek istediğimizde
4 ) Sınıfı ya da nesneyi tanımlarken
5 ) Aykırı Durumları (Exception) ele alırken

PointCuts, pointcut anahtar kelimesi ile deklare edilir. Join Points seçmek için kullanır ya da tanımlanmasını sağlar.

[visibility-modifier] pointcut name( ParameterList ) :PointcutExpr ;

Advice, PointCuts ile ilişkilendirilir ve metodu çalıştırmadan önce mi, yoksa sonra mı, kısaca metodun davranışını belirler, pointcuts lar üzerinde ne gibi işlem yapacağımıza burda karar veririz. Advice ile kullanılan terimler before Pointcuts’ın işletimine geçmeden önce ele alınmasını sağlar.after Pointcuts’ın işletimi bittikten sonra ele alınmasını sağlar.

Uygulamamızı bir örnekle açıklayalım.
package helloworld;

public aspect World {

//pointcut greeting() : execution(* Hello.sayHello(..));

//pointcut greeting() : call( * Hello.sayHello(..) );

pointcut greeting() : call( void sayHello(..) );

after() returning() : greeting() {
System.out.println(" World!");
}

before() : greeting(){
System.out.print("Asin Akdeniz...");
}

}

public class Hello {
public static void main(String[] args) {
sayHello();
}

public static void sayHello() {
System.out.print("Hello");
}
}

Burada Word AspectJ sınıfı, Hello nesnesine ait sayHello metodunun davranışına yön verir. Yani sayHello metodu çağrılmadan önce ve sonrasında bir dizi işlem yapılır. Örnekte sadece sayHello metodu çağrılmadan önce ve sonrasında ekrana bir şeyler yazmaktadır. Anlaşılır ve net bir örnek olduğu kanısındayım. Bu kodu eclipse ide’sinde deneyebilirsiniz ama oncelikle bazı plug-in’leri eklemeniz gerekmektedir. http://www.eclipse.org/aspectj/ linkinden gereken plug-in leri indirebilirsiniz.

14 Nisan 2008 Pazartesi

Bridge Pattern

Bridge örüntüsünün diğer örüntülere göre daha kompleks bir yapısı var lakin çok kullanışlı bir örüntü olduğunu deyinmeden de geçemem. Örüntümüzü örnek bir problemle ve bu probleme bakış açımızla adım adım ilerleyerek çözelim.
Daire çizmek için gereksinimiz drawCircle(x, y, r)
Çizgi çizmek için drawLine(x1, y1, x2, y2);

Bizden istenen dörtgen çizmemiz;
abstract class Rectangle {
public void draw () {
drawLine(_x1,_y1,_x2,_y1);
drawLine(_x2,_y1,_x2,_y2);
drawLine(_x2,_y2,_x1,_y2);
drawLine(_x1,_y2,_x1,_y1);
}
abstract protected void drawLine ( double x1, double y1,
double x2, double y2);
}
Bu seferde daire çizmemiz isteniyor.
abstract class Circle {
public void draw () {
drawCircle(x, y, r)
}
abstract protected void drawCircle ( double x, double y, double r);
}

Başka bir şekil istendiğinde, örneğin üçgen, yine soyut bir sınıfla tanımlamalarımızı yaparız ve onu extend eden bir sınıf yaratıp kullanırız. Fazla kötü gözükmüyor. Burda soyut sınıf kullanmadan da kodlamak mümkün. Biraz daha düşünmek gerekirse yukarıdaki örneklerden her şeklin çizimi kendi içinde. Açık kaynak proje ürettiğimizi düşünürsek başka bir yazılımcı benim yazdığım çizimlerden daha iyisini yapıyor. Bu durum herzaman mümkün daha iyisi vardır ya da daha iyisi olacak en büyük yanılgı yazdığı kodun en iyisi olduğunu düşünmektir. Daha iyisi yazılmış kodu kendi kodumuza entegre etmek bayağı zaman alacak gibi gözüküyor. Bu durumu düşünerek kodumuzu biraz daha bağımsız, modüler yapmaya çalışalım. Şekilleri ayrı, çizimleri ayrı düşünelim. Java programlama dili çoklu kalıtım desteği vermemektedir. Bizde şekil ve çizim tasarımlarımızı ayrı ayrı yapalım. Birini diğerine parametre geçirelim.

Kodu toparlayalım biraz;
abstract class Drawing{
abstract void drawLine ( double x1,double y1,double x2, double y2);
abstract void drawCircle ( double x, double y, double r);
}
class V1Drawing extends Drawing {
public void drawLine ( double x1,double y1, double x2,double y2) {
//Line kodu yazılır.
}
public void drawCircle ( double x,double y,double r) {
//Circle kodu yazılır.
}
}
abstract class Shape{
private Drawing dp;
Shape(Drawing dp;){ this.dp = dp}
abstract void draw();
public void drawLine drawLine ( double x1, double y1, double x2, double y2){
dp. drawLine(x1, y1, x2, y2);
}
public void drawCircle ( double x, double y, double r){
dp. drawCircle(x, y, r);
}
}

class Rectangle extends Shape {
public Rectangle ( Drawing dp, double x1,double y1, double x2,double y2) {
super( dp) ;
_x1= x1; _x2= x2 ;
_y1= y1; _y2= y2;
}
public void draw () {
drawLine(_x1,_y1,_x2,_y1);
drawLine(_x2,_y1,_x2,_y2);
drawLine(_x2,_y2,_x1,_y2);
drawLine(_x1,_y2,_x1,_y1);
}
}
class Circle extends Shape {
public Circle ( Drawing dp, double x,double y,double r) {
super( dp) ;
_x= x; _y= y; _r= r ;
}
public void draw () {
drawCircle(_x,_y,_r);
}
}

class Client {
public static void main(String argv[]) {
Shape r1, r2;
Drawing dp;
dp= new V1Drawing();
r1= new Rectangle(dp,1,1,2,2);
dp= new V2Drawing ();
r2= new Circle(dp,2,2,3);
r1.draw();
r2.draw();
}
}

Böylece dairemizi ve dörtgenimizi uygun bir çözümle yaratmış oluruz, az onceki problemize bir çözüm sunmuş durumdayız yani
dp= new V1Drawing();
yerine dp = new OtherDrawing(); //Bizden daha iyi kodlamış çizim sınıfını bu şekilde kendi kodumuzda çok az bir değişiklikle entegre edebiliriz.

Shape r1, r2;
Drawing dp;
dp= new V1Drawing();
r1= new Rectangle(dp,1,1,2,2);
dp= new V2Drawing ();
r2= new Circle(dp,2,2,3);
r1.draw();


Alan Shalloway, James R. Trott , Software Patterns Series kitabından alıntı yapılmıştır.

Facade Pattern

Nedir facade örüntüsü? Nerde ihtiyaç duyarım, nasıl kullanırım? Facede örüntüsü alt sistemin arayüzlerini kontol altına almaya çalışan birleşik bir arayüz(interface) sunmaktadır. Daha açıklayıcı olmak gerekirse yapılmış bir sistemin yapısını bozmadan, alt sistemlerin arayüzlerini kullanarak daha derli toplu bir arayüz sunmak ve bizim bu alt sistemi daha iyi, aktif ve doğru kullanmamıza olanak sunmak.
Terimlerimiz:
Amaç: Var olan sistemi daha basit bir şekilde nasıl kullanırım.
Problem: Kompleks bir sistemi daha akıcı ve sade nasıl yapabilirim.
Çözüm: Facade örüntüsünün çözüm sunduğu bir arayüz tasarlayıp alt sistem kaynaklarını istemciye tek elden erişilebilir bir hale getirmek.

Alan Shalloway, James R. Trott , Software Patterns Series

Şekil 2
Şekil2 de iki tane istemcinin(client) var olan bir sistemin kaynaklarını kullanmasını goruyoruz. Burda beliren sorun da tüm çıplaklığı ile gözüküyor. İstemcinin birden fazla alt sisteme erişmesi, kopleks yapının oluşmasına neden oluyor. Modelleme de bile karmaşıklık göze çarpıyor, bu işin kodlama aşamasını düşünmek ürkütücü geliyor. Bu yazıyı okuyan arkadaşların belki facade gerek olmadığını düşünüyorsa,
1) Sistemin birden çok alt sistemden oluştuğunu düşünürsek
Sorun: Aynı sürecin birden fazla programcı tarafında yapılması yani aynı kodun büyük bir projede tekrarlanıp durması.
XX adlı Muhendisinin kodu
A kaynağına eriş
A dan doneni B kaynağına yolla
B den doneni C ye yolla ve dönen değeri kullan.

YY adlı Muhendisinin kodu
A kaynağına eriş
A dan doneni B kaynağına yolla
B den doneni C ye yolla ve dönen değeri kullan.

2) İki mühendisin aynı yetkinlikte olmaması.
Sorun : Kaynakların doğru ve etkin kullanılmaması.
Bunu da unutmamak lazım: Yazdığınız kodun sizden sonraki mühendis tarafından okunabilir olması ve taktirle karşılanması mühendislik etiği kavramlarını oluşturmaktadır

Singleton Pattern

Singleton Örüntüsünde amacımız sınıfımıza ait sadece bir tane nesne yaratmak ve bu sınıfa erişmek istediğimizde bize aynı nesnenin refaransını döndermesidir.

Anahtar Sözcükler:
Amaç: Sadece bir tane nesne yaratmak ve nesne global tanımlanmayacak.
Problem:Birden fazla istemcinin bir sınıfa ait nesneye ihtiyaç duyması durumunda, dikkat edilmesi gereken istenen sınıfa ait birden fazla nesne yaratmamak.
Çözüm : Sadece bir nesne yaratmayı garanti etmek.
Kodlarken:
1) İstenen sınıfın üyesini static ve private tanımlamak ve başlangıçta ki değerine NULL atamak.
2) Constructor’ı protected ve private belirtmek.

Burda dikkat edilmesi gereken durumlardan biride sınıfa ait nesneyi yaratırken iki farklı istemcinin aynı anda sınıfı yaratan methoda erişmesidir. Burada çoklu thread’den bahsediyoruz. İki thread’in, sınıfı yaratan metoda aynı anda erişmesi, sınıda ait nesnenin yaratılmadığını varsayarsak, aynı anda ikisinin sınıfa ait nesneyi yaratmaya çalışması sıkıntıya neden olacaktır, bu nedenle yapacağımız Java örneğinde synchronized kullanacağız, bu da ikili kitlemeyi engelleyecek. İlk görev senkronize’ye girdi mi diğer görevler ilk görevin çıkmasını beklemek zorundadır, bu da kilitlenme sorununu çözer.

//wikipedia J Java5
public class Singleton {
private static volatile Singleton INSTANCE = null;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null)
synchronized(Singleton.class) {
if (INSTANCE == null)
INSTANCE = new Singleton();
}
return INSTANCE; }
}