SCEA 5 (Sun Certified Enterprise Architect)

Bugün itibariyle SCEA 5 (Sun Certified Enterprise Architect) sertifikasını almış bulunuyorum. Bir seneye yayılan sertifikasyon sürecinde üç değişik sınav yaparak, bu sertifikayı edindim. Gerçekten kolay değildi, bir de JEE 5 alanında uzman olduğumu düşünürdüm ;-)

SCEA 5 sertifikası Sun tarafından sunulan Java sertifikasyon programının en en son kademesinde bulunan ve yazılım mimarisi ile uğraşan yazılımcıların edinebilecekleri bir sertifika. SCEA 5 sertifikasyon süreci üç sınavdan oluşuyor. İlk sınav JEE 5 teknolojisini kapsayan iki ya da daha fazla seçenekli sorulardan oluşuyor. İkinci sınav bir JEE 5 projesini kapsıyor. Sun, sertifika adayına üzerinde çalışmak üzere bir proje tayin ediyor. Sertifika adayı Sun tarafından belirlenen kriterler doğrultusunda JEE 5 teknolojisi ile örnek bir çözüm hazırlayarak, çözümünü Sun’a iletiyor. Son sınavda sertifika adayı geliştirdiği proje hakkında sorular cevaplayarak, çözümün kendisine ait olduğunu ispatlamak zorunda.

Sun Java sertifikasyon programi hakkında detayları bu link üzerinden edinebilrisiniz

Kaynak Kitaplar

  • Java Design Patterns
  • EJB 3 in Action
  • The J2EE Architects’s Handbook
  • Mastering Enterprise JavaBeans 3.0
  • Core J2EE Design Patterns
  • Sun Certified Enterprise Architecture for J2EE Technology Study Guide
  • KurumsalJava.com Tasarım Şablonları Bölümü
    • Sertifikasyon İÇERİĞİ

      SCEA 5 üç bölümden (sınav) oluşuyor. Bunlar

      • CX-310-052
      • CX-310-301A
      • CX-310-062

      CX-310-052

      SCEA sertikasyonunun ilk basamağını CX-310-052 sınavı oluşturuyor. Bu sınavın kapsadığı alan şu şekilde:

      Section 1: Application Design Concepts and Principles

      • Explain the main advantages of an object-oriented approach to system design including the effect of encapsulation, inheritance, and use of interfaces on architectural characteristics.
      • Describe how the principle of “separation of concerns” has been applied to the main system tiers of a Java Platform, Enterprise Edition application. Tiers include client (both GUI and web), web (web container), business (EJB container), integration, and resource tiers.
      • Describe how the principle of “separation of concerns” has been applied to the layers of a Java EE application. Layers include application, virtual platform (component APIs), application infrastructure (containers), enterprise services (operating system and virtualization), compute and storage, and the networking infrastructure layers.

      Section 2: Common Architectures

      • Explain the advantages and disadvantages of two-tier architectures when examined under the following topics: scalability, maintainability, reliability, availability, extensibility, performance, manageability, and security.
      • Explain the advantages and disadvantages of three-tier architectures when examined under the following topics: scalability, maintainability, reliability, availability, extensibility, performance, manageability, and security
      • Explain the advantages and disadvantages of multi-tier architectures when examined under the following topics: scalability, maintainability, reliability, availability, extensibility, performance, manageability, and security.
      • Explain the benefits and drawbacks of rich clients and browser-based clients as deployed in a typical Java EE application.
      • Explain appropriate and inappropriate uses for web services in the Java EE platform

      Section 3: Integration and Messaging

      • Explain possible approaches for communicating with an external system from a Java EE technology-based system given an outline description of those systems and outline the benefits and drawbacks of each approach.
      • Explain typical uses of web services and XML over HTTP as mechanisms to integrate distinct software components.
      • Explain how JCA and JMS are used to integrate distinct software components as part of an overall Java EE application.

      Section 4: Business Tier Technologies

      • Explain and contrast uses for entity beans, entity classes, stateful and stateless session beans, and message-driven beans, and understand the advantages and disadvantages of each type.
      • Explain and contrast the following persistence strategies: container-managed persistence (CMP) BMP, JDO, JPA, ORM and using DAOs (Data Access Objects) and direct JDBC technology-based persistence under the following headings: ease of development, performance, scalability, extensibility, and security.
      • Explain how Java EE supports the deployment of server-side components implemented as web services and the advantages and disadvantages of adopting such an approach.
      • Explain the benefits of the EJB 3 development model over previous EJB generations for ease of development including how the EJB container simplifies EJB development.

      Section 5: Web Tier Technologies

      • State the benefits and drawbacks of adopting a web framework in designing a Java EE application
      • Explain standard uses for JSP pages and servlets in a typical Java EE application.
      • Explain standard uses for JavaServer Faces components in a typical Java EE application.
      • Given a system requirements definition, explain and justify your rationale for choosing a web-centric or EJB-centric implementation to solve the requirements. Web-centric means that you are providing a solution that does not use EJB components. EJB-centric solution will require an application server that supports EJB components.

      Section 6: Applicability of Java EE Technology

      • Given a specified business problem, design a modular solution that solves the problem using Java EE.
      • Explain how the Java EE platform enables service oriented architecture (SOA) -based applications.
      • Explain how you would design a Java EE application to repeatedly measure critical non-functional requirements and outline a standard process with specific strategies to refactor that application to improve on the results of the measurements.

      Section 7: Patterns

      • From a list, select the most appropriate pattern for a given scenario. Patterns are limited to those documented in the book – Alur, Crupi and Malks (2003). Core J2EE Patterns: Best Practices and Design Strategies 2nd Edition and named using the names given in that book.
      • From a list, select the most appropriate pattern for a given scenario. Patterns are limited to those documented in the book – Gamma, Erich; Richard Helm, Ralph Johnson, and John Vlissides (1995). Design Patterns: Elements of Reusable Object-Oriented Software and are named using the names given in that book.
      • From a list, select the benefits and drawbacks of a pattern drawn from the book – Gamma, Erich; Richard Helm, Ralph Johnson, and John Vlissides (1995). Design Patterns: Elements of Reusable Object-Oriented Software.
      • From a list, select the benefits and drawbacks of a specified Core J2EE pattern drawn from the book – Alur, Crupi and Malks (2003). Core J2EE Patterns: Best Practices and Design Strategies 2nd Edition.

      Section 8: Security

      • Explain the client-side security model for the Java SE environment, including the Web Start and applet deployment modes.
      • Given an architectural system specification, select appropriate locations for implementation of specified security features, and select suitable technologies for implementation of those features
      • Identify and classify potential threats to a system and describe how a given architecture will address the threats.
      • Describe the commonly used declarative and programmatic methods used to secure applications built on the Java EE platform, for example use of deployment descriptors and JAAS.

      Sinav için hazırlıklarınızı tamamladıktan sonra Sun’a 200 dolar ödeyerek, bu sınava girebiliyorsunuz. Sınav yeri Prometric üzerinden belirlenebiliyor.

      CX-310-301A

      Birinci sınavı (CX-310-052) başarıyla tamamladıktan sonra sırada SCEA 5’in ikinci basamağı olan CX-310-301A yer almaktadır. Bu bir sınavdan ziyade JEE 5.0 teknolojisi ile geliştirilmiş bir projedir. Sertifika adayının JEE 5.0 teknoloji bütününü kullanarak verilen kriterler doğrultusunda projeyi tamamlaması ve Sun firmasına iletmesi gerekmektedir. Bana Sun tarafından Dreamcar projesi tayin edildi. Gizlilik prensipleri doğrultusunda burada ne yazik ki tüm detayları açıklamam mümkün değil. Lakin birkaç cümle ile gidişatın nasıl olduğunu sizlere aktarmak isterim.

      CX-310-301A çercevesinde Sun, sertifika adayının mevcut bir proje üzerinde mimari oluşturma ve açıklama yeteneklerini sınamaktadır. Sertifika adayının, proje gereksinimlerinin UML diagramları oluşturarak nasıl çözümlenebileceklerini açıklamaklası gerekmektedir. Sertifika adayı 6-10 arası değişen proje gereksinimini (requirement) Sequence Diagram, Class Diagram, Components Diagram ve Deployment Diagram kullanarak, oluşturduğu çözümü UML diagramları aracılığıyla görselleştirir. Sertifika adayının oluşturduğu çözümlerde hangi teknolojiyi ve tasarım şablonlarını kullandığını detaylandırması gerekmektedir. Dreamcar projesi için kullandığım tasarım şablonları şu şekilde idi:

      Presentation tier: MVC – Model View Controller

      MVC is used in most of the popular web frameworks (JSF, Struts…). In my implementation I used the domain objects as models, Java Server Pages as views and servlets as controller. View is only responsible for displaying data to the user. Navigation, validation and business logic access is done in controller classes.

      Presentation tier: View Helper

      Business domain objects are also used as view helpers when rendering JSPs.

      Presentation tier: Business Delegate

      In order to hide the complexity of accessing remote business logic (EJB) from clients I used a BusinessDelagate class.

      Presentation tier: Service Locator

      The BusinessDelegate class uses internally a ServiceLocator class to locate the remote business logic classes via JNDI calls. It caches remote interface instances to speed up the access to remote objects.

      Business tier: Session Facade

      The stateless session beans are used as session facade classes. The session facade centralizes and controls the access to business logic.

      Business tier: Business Object (BO)

      I used business object classes to encapsulate the business logic. The session beans uses the business object to delegate the business logic calls the business object instances. With business objects the business logic is encapsulated and reusable.

      Database tier: Data Access Object (DAO)

      I used DAO to isolate the database access for business tier. The business tier should not know any specific details about data storage. One can use other DAO implementations to change the data storage kind.

      Database tier: Domain Store

      I used the domain store design pattern to seperate persistance from my object model. JPA Entity manager is used to persist the busines domain objects.

      Sertifika adayından kod yazması beklenmemektedir. Çözümlerin UML diagramları aracılıği ile oluşturulmuş olması yeterlidir.

      CX-310-062

      Sertifikanın üçüncü basamağı CX-310-062‘dır. Bu sınavı yapabilmek için ikinci basamakta sertifika adayına verilen projenin tamamlanmış ve Sun’a iletilmiş olması gerekmektedir. Bu basamakta sertifika adayı, ikinci basamakta oluşturduğu çözüm hakkında kendisine sorulan soruları cevaplamak zorundadır. Bu şekilde sertifika adayının ikinci basamakta oluşturduğu çözümün kendisine ait olup, olmadıği kontrol edilmektedir.

      Sonuç

      Yazılım mimarisi ve Java ile uğraşan yazılımcıların gözdesi olan SCEA 5 sertifikası kolay elde edilebilecek bir sertifika değil. Bu sebepten dolayı da kıymetli ve itibarlı bir serfikadır. Sertifika adayının J2EE ve JEE 5 teknolojilerini yakından tanıması ve çalıştığı projelerde bu teknolojileri kullanmış olması, SCEA 5 sertifikasını edinmesini kolaylaştırmaktadır.

      SCEA 5 sertifikası diğer Java sertifikalarından bağımsız olarak alınabilmektedir. Bu sertifika için herhangi bir ön koşul bulunmamaktadır.


      Özcan Acar
      Java Champion, SCEA 5

Türkiye’den İlk Java Champion Özcan Acar

Bugün Java Champion olarak seçildim. Benim için çok mutlu bir gün, çünkü bir Java yazılımcısının edinebileceği en yüksek ünvanlardan birisi Java Champion ünvanıdır. James Gosling, Bill Burke, David Flanagan ve Josh Bloch gibi tanınmış sahışların Java Champion ünvanına sahip olduklarını ve dünya çapında 100 civarında Java Champion ünvanına sahip yazılımcının olduğunu düşünürsek bu ünvanın ne kadar itibarlı ve kıymetli olduğunu görebiliriz.

Bir Java Champion nedir? Bu konu hakkında detaylı bilgiyi Java Champion websayfasından edinebilirsiniz. Java Champion Sun tarafından hayata geçirilmiş ve desteklenen bir proje. Java Championlar Sun tarafından seçilmemektedir. Java Champion adayları, mevcut Java Championların kendi aralarında yaptıkları oylama sonucunda bu ünvanı kazanırlar. Java Championlar Sun firmasından bağımsız olarak çalışan, Java platformunun gelişmesine katkıda bulunan yazar, eğitmen, senior mimar ve yazılımcılardır.


Resim 1

Java Champion listesinde ismimi görebilirsiniz.

Özcan Acar
Java Champion

Write Through Cache

Sürücü üzerinde (disk) ya da hafıza (memory) da yer alan ve verinin depolandıktan sonra alındığı ön belleğe write through cache ismi verilmektedir. Bu şekilde veri deposuna eklenmiş olan veri ön belleğe de eklenmiş olur. Write through cache sayesinde verilerin, veri deposuna eklenme performansı artırılmazken verilerin tekrar edinilme işlemi hızlandırılmış olur.

Intercepting Filter Tasarım Şablonu

Front Controller tasarım şablonunda, kullanıcıdan gelen isteklerin (request) merkezi bir yerde toplanarak, işlem yapıldığını daha önce görmüştük. Intercepting Filter tasarım şablonu ile, kullanıcının isteği (request) işleme alınmadan önce filtreler kullanılarak süzgeçten geçirilir. Örneğin bir filtre ile kullanıcının işlem öncesi login yaptığını konrol edebiliriz. Filtremiz, session (HttpServletSesion) içinde login bilgilerini bulamadığı taktirde, kullanıcıyı login sayfasına yönlendirebilir.

Aynı şekilde işlem tamamlandıktan sonra kullanıcıya gönderilecek cevap (response) filtreler yardımı ile modifike edilebilir.

Bu yazıyı PDF olarak edinebilirsiniz.

  Intercepting Filter Tasarım Şablonu (55,1 KiB, 7.577 yükleme)


EOF (End of Fun)
Özcan Acar

Reuse-Release Equivalence Principle (REP) – Tekrar Kullanım ve Sürüm Eşitliği

Program modülleri paketler (packages) kullanılarak organize edilir. Paketler arasında sınıfların birbirlerini kullanmalarıyla bağımlılıklar oluşur. Bunun bir örneği resim 1 de yer almaktadır. Eğer paket B bünyesindeki bir sınıf paket A bünyesinde bulunan bir sınıf tarafından kullanılıyorsa, bu paket A’nin paket B’ye bağımlılığı olduğu anlamına gelir. Bu tür bağımlılıkların oluşması doğaldır. Amaç bu bağımlılıkları ortadan kaldırmak değil, kontrol edilebilir hale getirmek olmalıdır. Bu amaçla paket bazında uygulanabilecek tasarım prensipleri oluşturulmuştur. Bunlardan birisi Reuse-Release Equivalence (tekrar kullanım ve sürüm eşitliği) prensibidir.

Bir proje bünyesinde değişik modüllerden oluşan bir yazılım sistemini implemente etmek için çalıştığımızı düşünelim. Her modülden ayrı bir ekip sorumlu olsun. Üzerinde çalıştığımız modülün implementasyonunu yapabilmek için büyük bir ihtimalle diğer modülleri kullanmamız gerekecektir. Örneğin bilgibankası üzerinde işlem yapmamızı sağlayacak bir modülü başka bir ekip implemente etmiş olabilir. O ekip bilgibankası üzerindeki işlemler için gerekli tüm sınıfları dao isimli bir paket içine yerleştirmiş olabilir. Bizim bu paket içindeki sınıfları tekrar kullanabilmemiz (reuse) için belirli şartların yerine gelmesi gerekmektedir. Bunlar:

  • Bilgibankası ekibi, bilgibankası üzerinde işlem yapmak için kullanılan tüm sınıfları, bu sınıflar birbirleriyle ilişkili olduğu için aynı paket içine koymalıdır. Bu tekrar kullanımı kolaylaştırır.
  • Tekrar kullanımı desteklemek için oluşturulan paketin bir versiyon numarasıyla yeni sürümünün oluşturulması gerekmektedir.
  • Paket kullanıcıları paket üzerinde yapılan değişikliklerden haberdar edilmelidir. Onlar için kullanabilecekleri yeni bir paket sürümünün oluşturulması yanı sıra, mevcut kodun kırılmasını önlemek için paketin eski versiyonlarının da paralel kullanıma açık tutulması gerekir. Sadece bu durumda paket kullanıcıları paket üzerinde yapılan değişiklerinden etkilenmeden eski versiyonlarla çalışmaya devam edebilirler. Zaman içinde yeni paket versiyonuna geçerek, son değişiklikleri entegre ederler.

Tekrar kullanımı kolaylaştırmak için paket sürümlerinin oluşturulması şarttır. REP’e göre tekrar kullanılabilirlik (reuse) sürüm (release) ile direk orantılıdır. Sürüm ne ihtiva ediyorsa, o tekrar kullanılabilir.

Bu yazıyı PDF dosyası olarak aşağıdaki linkten edinebilirsiniz.


EOF (End of Fun)
Özcan Acar

JPA Anotasyonları ve Dinamik Tablo İsmi

Projelerde komponent tabanlı çalışmaya özen gösteriyorum. Komponent olarak geliştirdiğim bir modülü, konfigürasyon değişikliği yaparak başka bir projede kullanabilmeliyim. Komponentler kodun tekrar kullanımını (reuse) ve programcının daha az kod yazmasını mümkün kılar.

Komponent bünyelerinde Hibernate kullanarak, komponent verilerini bilgibankasında sakliyorum. Şu an geliştirdiğim JugTR.org projesinde JPA anotasyonlarını kullandım. Aşağıda blog kayıtlarını temsil eden Blog Entity sınıfı yer alıyor.

[source language=’java’]
package bt.common.manager.blog.domain;

import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name=”blog”)
public class Blog implements Serializable
{
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = “id”)
private Long id;

@Column(name = “subject”, nullable = false)
private String subject;

@Column(name = “body”, nullable = false)
private String body;

@Column(name = “userid”, nullable = false)
private Long user;

@Column(name = “created”, nullable = false)
private Timestamp created;

public Blog(long blogId)
{
this.id = blogId;
}

public Blog()
{

}

public Long getId()
{
return id;
}

public void setId(Long id)
{
this.id = id;
}

public String getSubject()
{
return subject;
}

public void setSubject(String subject)
{
this.subject = subject;
}

public String getBody()
{
return body;
}

public void setBody(String body)
{
this.body = body;
}

public Long getUser()
{
return user;
}

public void setUser(Long user)
{
this.user = user;
}

public Timestamp getCreated()
{
return created;
}

public void setCreated(Timestamp created)
{
this.created = created;
}
}
[/source]

@Table anotasyonunu kullanarak bilgibankası tablosunu belirliyorum. Örnekte görüldüğü gibi Blog nesnesinin ihtiva ettiği veriler blog isimli tabloda saklanmakta.

Blog komponentini (Blog.java ve diger komponent sınıfları) daha önce başka projelerde de kullandım. Komponenti tekrar kullanmak (reuse) benim için kod üzerinde değişiklik yapmamak anlamına gelmektedir. Eğer blog verilerini jugtr_blog isimli tabloda tutmak istersem, Blog.java sınıfında yer alan @Table anotasyonunu değiştirmem gerekiyor. Bu durumda komponentin kodunu değiştirmiş olacağım. Bu da bir nevi tekrar kullanım, lakin bu durumda komponentin birden fazla versiyonu oluşmakta ve bunların bakımı zamanla güçleşmektedir. Benim hayalimde kod üzerinde değişiklik yapmadan Blog komponenentini istediğim projede kullanabilmek ve bilgibankası tablo ismini projeye göre değiştirebilmek var. Bu ne yazik ki JPA anotasyonlarını kullanarak mümkün değil. Eğer @Table anotasyonu ile tablo ismini belirlediyseniz, o zaman tablo ismini değiştirmek için sınıfı değiştirmeniz gerekiyor.

Bu çoktan beri üzerinde çalıştığım bir sorun. Sorunu Hibernate bünyesinde bir interceptor sınıf oluşturarak çözebildim. Interceptor sınıfı aşağıdaki yapıya sahip:

[source language=’java’]
package bt.jugtr.application.common.hibernate;

import org.hibernate.EmptyInterceptor;

public class JugTRHibernateInterceptor extends EmptyInterceptor
{

private static final long serialVersionUID = 1L;

@Override
public String onPrepareStatement(String sql)
{
String prepedStatement = super.onPrepareStatement(sql);

prepedStatement = prepedStatement.replaceAll(“public.”, “jugtr.”);

return prepedStatement;
}
}
[/source]

Bu interceptor sınıfını aktive etmek için SessionFactory konfigürasyonunu (Spring applicationContext.xml bünyesinde) aşağıdaki şekilde değiştiriyorum:

[source language=’java’]
org.hibernate.cfg.AnnotationConfiguration ${hibernate.dialect} true true true after_transaction thread bt.common.manager.user.domain.BTUser
bt.common.manager.user.domain.Authorities
bt.common.manager.blog.domain.Blog
bt.common.manager.blog.domain.BlogComment


[/source]

Hibernate, oluşturduğu SQL komutunu bilgibankasına göndermeden önce JugTRHibernateInterceptor sınıfının onPrepareStatement() metodunu koşturur. Bu metot bünyesinde public. ile başlayan tablo isimlerini jugtr. olarak değiştiriyorum. public. ve jugtr. bilgibankasında kullandığım şemalar (schema). Hibernate tarafından oluşturulan SQL komutlarında public. isminin kullanımını @Table anotasyonuna schema değişkenini ekleyerek sağlayabilirim:

[source language=’java’]
@Entity
@Table(name=”blog”, schema=”public”)
public class Blog implements Serializable
{
}
[/source]

Bu değişikliğin ardından Hibernate tarafından oluşturulan bir SQL aşağıdaki şekilde olacaktır:

[source language=’java’]
/* from Blog order by id desc */
select top ? blog0_.id as id2_, blog0_.body as body2_, blog0_.created as created2_, blog0_.subject
as subject2_, blog0_.userid as userid2_ from public.blog blog0_ order by blog0_.id desc
[/source]

Görüldüğü gibi Hibernate blog tablosunu public.blog seklinde adreslemeye başladı. Tekrar JugTRHibernateInterceptor sınıfına geri dönelim. onPrepareStatement() metodu bünyesinde SQL komutunda yer alan public. kelimesinin jugtr. olarak değiştirilmesini sağlıyorum. Bu şekilde dinamik olarak başka bir şemayı ve bu şemada bulunan blog tablosunu adreslemiş oluyorum. JugTRHibernateInterceptor devreye girdikten sonra SQL komutu aşağıdaki şekilde değişikliğe uğruyor. Bu şekilde başka bir şema içinde bulunan blog isimli tablo kullanımı mümkün oluyor. Görüldüğü gibi Blog.java kodunu değiştirmek zorunda kalmadan başka bir tabloyu kullanabildik.

[source language=’java’]
/* from Blog order by id desc */
select top ? blog0_.id as id2_, blog0_.body as body2_, blog0_.created as created2_, blog0_.subject
as subject2_, blog0_.userid as userid2_ from jugtr.blog blog0_ order by blog0_.id desc
[/source]


EOF ( End Of Fun)
Özcan Acar

Apache ile Tomcat Arasında Reverse Proxy Oluşturma

JugTR.org projesi Tomcat içinde deploy edilen bir Java 6 web aplikasyonu (Servlet 2.5 spec).  Bu aplikasyona http://www.jugtr.org adresi üzerinden ulaşabilmek için Tomcat’in 80 numaralı port üzerinde çalışması gerekmektedir. Kullandığım server üzerinde 80 numaralı portta Apache çalışmakta. Bu durumda Tomcat’i 80 numaralı port üzerinde çalıştırmam mümkün değil.  80 haricinde herhangi bir port seçerek, JugTR.org aplikasyonunu deploy edebilirim, örneğin port 8181. Bu durumda aplikasyonun erişim adresi http://www.jugtr.org:8181 olacaktır.

Apache ile Tomcat arasında Reverse Proxy oluşturarak JugTR.org aplikasyonuna 80 numaralı port üzerinden ulaşabiliriz. Reverse Proxy kullanıldığında http://www.jugtr.org adresine gelen kullanıcı istekleri Apache tarafından http://127.0.0.1:8181 adresine yönlendirilir ve bu şekilde 8181 portu üzerinde faaliyet gösteren Tomcat’e 80 numaralı port üzerinden erişim sağlanmış olur. Apache,  kullanıcı ile Tomcat içinde deploy edilmiş ve 8181 numaralı portta çalışan JugTR.org aplikasyonu arasında aracılık etmiş olur.

Apache ile Tomcat arasında Reverse Proxy oluşturmak için öncelikle mod_proxy modülünü Apache httpd.conf dosyasina eklememiz gerekiyor. Ben Apache 2 versiyonunu kullanıyorum. Aşağıda httpd.conf dosyasında yer alması gereken konfigürasyon bulunmakta.

 

[source language=’java’]

LoadModule proxy_module modules/mod_proxy.so

[Proxy *]
Order deny,allow
Allow from all
[/Proxy]

NameVirtualHost 192.168.1.76

[VirtualHost 192.168.1.76]
ServerName www.jugtr.org
ServerAlias www.jugtr.org jugtr.org
ServerAdmin info@jugtr.org
DocumentRoot /database/usr/local/apache/htdocs/
ProxyPass / http://127.0.0.1:8181/
[Location /]
ProxyPassReverse /
[/Location]
[/VirtualHost]

[/source]

Yukarda görüldügü gibi VirtualHost direktifini kullanarak, jugtr.org icin yeni bir virtual domain oluşturuyorum. Bu sayede aynı Apache kurulumu üzerinde birden fazla domain ismini kullanmam mümkün.

VirtualHost direktifini yakından incelediğimizde ProxyPass direktifi ile http://www.jugtr.org/ adresine gelen tüm kullanıcı isteklerinin (request) http://127.0.0.1:8181 adresine yönlendirildiğini görmekteyiz. ProxyPass direktifini kullanarak Apache ve Tomcat arasında Reverse Proxy oluşturmus oluyoruz.

Tomcat kullanıcı isteklerine konfigüre edildigi IP ve port adresi ile cevap verir. Yukardaki örnekte kullanıcı http://127.0.0.1:8181 adresine yönlendirilecektir. Bu durumda Apache ile Tomcat arasındaki proxy çalışmamaktadır. Tomcat’in gönderdigi cevapların reverse proxy adresinde olmasını sağlamak için Tomcat’in server.xml konfigürasyon dosyası üzerinde değişiklik yapmamız gerekmektedir. Yapılması gereken değişiklik Connector elementi bünyesindedir.

[source language=’java’]

Connector port=”1224″ maxThreads=”150″ minSpareThreads=”25″ maxSpareThreads=”75″ enableLookups=”false” redirectPort=”8443″

debug=”0″ acceptCount=”100″ connectionTimeout=”20000″ disableUploadTimeout=”true” URIEncoding=”UTF-8″ proxyName=”www.jugtr.org” proxyPort=”80″

[/source]

Connector elementinde kullandığımız proxyName ve proxyPort atributlarıyla Tomcat’in gönderdiği cevapların http://www.jugtr.org şeklinde olmasını sagladık.

 

 

EOF ( End Of Fun )
Özcan Acar

 

 

 

Devoxx 2009 İzlenimleri

Geçen hafta Belçika’da düzenlenen Devoxx konferansına katıldım. Java ile ilgilenenlerin mutlaka katılması gereken bir konferans. Bir hafta boyunca değişik konularda, konularında uzman şahısların sunum yaptıkları bu konferansta James Gosling, Robert C. Martin, Chris Richardson, Scott Ambler gibi ustaları dinleme ve onlarla sohbet etme fırsatı bulabiliyorsunuz.

Aşağıda yer alan fotografları Devoxx’da çektim.


Resim 1

Resim 1 de Agile Mythbuster konulu sunumu yapan Scott Ambler yer almakta. Çevik süreçlerde oluşan bazı efsaneleri tematize eden bu sunumda Scott Ambler bazı efsanelerin nasıl oluştuğunu ve nasıl çürütüldüğünü istatistikler üzerinde dinleyicilere aktardı. En çok hoşuma giden efsane ise, çevik süreçlerde sertifikasyonun çok önemli olduğu idi. Scott Ambler’e göre 3 sene doktora yapmış bir şahıs ile 2 günlük bir seminer ardından sertifika almış bir şahısı aynı kefeye koymak çok mantık dışı :) Ben de kendisiyle aynı fikri paylaşıyorum. Sertifika peşinde koşmaktansa, konuyu derinlemesine araştırıp, anlamak ve uygulamak çok daha faydalı olacaktır.


Resim 2


Resim 3


Resim 4

Resim 4 de Architecting Robust Applications for Amazon EC2 konulu sunumu yapan Chris Richardson yer almakta. Chris Richardson POJO in Action konulu kitabın yazarı. Bu kitap yazılımcı kariyerimde beni en çok etkileyen kitaplardan birisidir. Chris Richardson ustayı Devoxx da dinleme firsatı bulmak benim için büyük bir şerefdi.


Resim 5

Resim 5 de Java’nın babası James Gosling ve ben yer alıyorum.

 

Resim 6

Resim 6 da programcılar için hazırlanan anketlerden birisi yer almakta. Resim 6 da yer alan ankette, programcılara kullandıkları yapılandırma (build tool) aracı sorulmuş. Çoğunluğu maven ve ant yapılandırma aracı oluşturmakta. Benim son zamanlardaki favorim maven.

Resim 7

Resim 7 de değişik ülkelerde faaliyet gösteren JUG (Java User Group) liderlerinin katıldığı toplantıdan bir resim yer almakta. Bu toplantıda JUG liderleri Java hakkındaki sorularını Java’nın babası James Gosling’e yönelttiler. Bu toplantıda bir çok JUG lideri ile tanışma firsatı buldum. Türkiye’de de bir JUG kurmanın zamanı geldi. Kısa bir zaman sonra JugTR.org adresinde Türkiye’nin ilk resmi JUG’u faaliyete geçecek. Bu konudakı çalışmalarım devam etmekte.

 


Resim 8


Resim 9


Resim 10


Resim 11


Resim 12

YAGNI

YAGNI = You Ain´t Gonna Need It = İhtiyacın Olmayan Birşeyi Oluşturma!

Extreme Programming prensiplerinden birisi olan YAGNI, JUnit test karşılığı olmayan ve ihtiyaç duyulmayan program kodunun programcılar tarafından oluşturulmamaları gerektiğini ifade eder. Test güdümlü çalışıldığı taktirde YAGNI prensibi uygulanmış olur. Testlerin olmadığı yerde YAGNI vardır :)


EOF ( End Of Fun)
Özcan Acar

KISS – Keep It Stupid Simple

KISS = Keep It Simple, Stupid (KISS) = Mümkün Olan En Basit Çözümü Seç!

KISS prensibine göre bir programcı, mevcut bir sorunu çözerken mümkün olan en basit çözümü seçmelidir. En basit çözüm genelde en optimal çözümdür. Genelde programcılar bir sorunun en basit çözümünü basit ve yetersiz gördüklerinden daha karmaşık çözümler üretirler, ama bilmezler ki KISS prensibine bu sekilde ters düşmüş olurlar :)


EOF ( End Of Fun)
Özcan Acar

DRY – Don’t Repeat Yourself

DRY = Don’t Repeat Yourself = Kendini Tekrarlama!

DRY prensibine göre programcının kodlama esnasında kod tekrarlarından (code duplication) sakınması gerekmektedir. Kodun kendini tekrarlaması (örneğin copy-paste metodu kullanılarak) yazılım sisteminin genelde bakımını ve geliştirilmesini zorlaştırır. Bunun önüne geçmek için azimle DRY prensibinin uygulanması gerekmektedir.


EOF (End Of Fun)
Özcan Acar

Interface Segregation Principle (ISP) – Arayüz Ayırma Prensibi

Birbiriyle ilişkili olmayan birçok metodu ihtiva eden büyük bir interface sınıf yerine, birbiriyle ilişkili (cohesive) metotların yer aldığı birden fazla interface sınıfı daha makbuldür.
ISP uygulanmadığı taktirde, birden fazla sorumluluğu olan interface sınıflar oluşur. Zaman içinde yüklenen yeni sorumluluklarla bu interface sınıflar daha da büyür ve kontrol edilemez bir hale gelebilir. Bunun bir örneğini resim 1 de görmekteyiz.

Resim 1 de yer alan Connector interface sınıfı bünyesinde JMS (Java Message Service) için gerekli iki metot bulunmaktadır: commit ve rollback. Bu metodlarin RMIConnector implementasyonunda implemente edilmeleri anlamsız olur. Büyük bir ihtimalle RMIConnector sınıfında bu metotların implementasyonu kod 1 de yer aldığı şekilde olacaktır.

[source language=’java’]
package shop;

public class RMIConnector implements Connector
{

public void commit()
{
throw new RuntimeException(“not implemented”);
}

public void rollback()
{
throw new RuntimeException(“not implemented”);
}
}
[/source]

Kod 1 de yer alan yapı LSP ile uyumlu değildir. Connector sınıfını kullananlar RuntimeException oluşabileceğini göz önünde bulundurmak zorunda bırakılmaktadırlar.

ISP uygulandığı taktirde resim 1 de yer alan Connector interface sınıfını yok ederek, yerine sorumluluk alanları belli iki yeni interface sınıf oluşturabiliriz. Resim 2 de bu çözüm yer almaktadır.

Programcı olarak bir interface sınıfa birden fazla sorumluluk yüklememek için, interface sınıfın sistemdeki görevini iyi anlamamız gerekmektedir. Bu sadece bir sorumluluk alanı olan bir interface sınıf oluşturmamızı kolaylaştıracaktır.

Bu yazıyı PDF dosyası olarak aşağıdaki linkten edinebilirsiniz.


EOF (End of Fun)
Özcan Acar

Test Güdümlü Yazılımın Tasarım Üzerindeki Etkileri

Yazılımcı olarak çalıştığım projelerde geleneksel ve çevik yazılım süreçleri hakkında tecrübe edinme firsatı buldum. En son kitabım bir çevik süreç olan Extreme Programming hakkındadır. Edindiğim tecrübeler doğrultusunda çevik süreçlerin, klasik yazılım süreçlerine nazaran bakımı ve geliştirilmesi daha kolay yazılım sistemlerinin oluşturulmasında daha avantajlı olduğunu söyleyebilirim.

Bu yazımda sizelere test güdümlü yazılım sürecinin, yazılım tasarımı üzerindeki etkilerini bir örnek üzerinde aktarmak istiyorum. TDD ile birlikte oluşan tasarım, kendiliğinden oluşan birşey değildir. Testler şekil aldıkça, oluşturmak istediğimiz tasarımın modeli de gözümüzde canlanmaya başlar. Oluşturduğumuz testler, programın gelecekteki kullanıcılarını (client) simule ettiği için, programın nasıl kullanılacağını testler bünyesinde gözlemlemek kolaylaşmaktadır. Bu süreç, sınıfların ve metotların kullanıcı gözüyle (client) tasarlanmasını sağlar. Bu sayede basit ve kullanışlı API (Application Programming Interface)’ler oluşur. Test güdümlü yazılım tasarımı devamlı zorlar ve yetersiz kaldığı yerlerde refactoring yöntemleriyle yenilenmesini sağlar. Bu süreç sayesinde kendisini devamlı yenileyen ve yeni gereksinimlere cevap veren bir tasarım oluşur.

Bu yazıyı PDF olarak edinebilirsiniz.


EOF (End of Fun)
Özcan Acar

Builder Tasarım Şablonu

Daha önceki bölümlerde Abstract Factory tasarım şablonu ile değişik nesne ailelerinden nasıl nesneler üretildiğini incelemiştik. Builder tasarım şablonu da Abstract Factory tasarım şablonunda oldugu gibi istenilen bir tipte nesne oluşturmak için kullanılır. İki tasarım şablonu arasındaki fark, Builder tasarım şablonunun kompleks yapıdaki bir nesneyi değişik parçaları bir araya getirerek oluşturmasında yatmaktadır. Birden fazla adım içeren nesne üretim sürecinde, değişik parçalar birleştirilir ve istenilen tipte nesne oluşturulur.

Diğer bölümlerde olduğu gibi bir örnek üzerinde bu tasarım şablonunu yakından inceliyelim.

Bu yazıyı PDF olarak edinebilirsiniz.

  Builder Tasarım Şablonu (53,6 KiB, 9.292 yükleme)


EOF (End of Fun)
Özcan Acar

Service Locator Tasarım Şablonu

Business Delegate örneğinde, Service Locator Tasarım şablonunun nasıl uygulandığını görmüştük. Service Locator, işletme (business) katmanında bulunan komponentlerin lokalizasyonu için kullanılır

Bu yazıyı PDF olarak edinebilirsiniz.

  Service Locator Tasarım Şablonu (35,3 KiB, 6.837 yükleme)


EOF (End of Fun)
Özcan Acar

Business Delegate Tasarım Şablonu

Modern yazılım sistemleri birden fazla katmandan oluşur. Bu katmanlar her zaman aynı server üzerinde mevcut olmayabilir. Bu durumda bir katmandan diger katmana ulaşmak için remote call olarak isimlendirilen RMI operasyonları yapılır. Örneğin EJB teknolojisi ile hazırlanan komponentler birden fazla server üzerinde hizmet sunabilir. Bu komponentlere bağlanıp, işlem yapabilmek için RMI kullanılır. Okumaya devam et →

Dependency Inversion Principle (DIP) – Bağımlılıkların Tersine Çevrilmesi Prensibi

Bu prensibe göre somut sınıflara olan bağımlılıklar soyut sınıflar ve interface sınıflar kullanılarak ortadan kaldırılmalıdır, çünkü somut sınıflar sık sık değişikliğe uğrarlar ve bu sınıflara bağımlı olan sınıflarında yapısal değişikliğe uğramalarına sebep olurlar.

Resim 1 de görülen yapı DIP prensibine ters düşmektedir, çünkü RemoteControl sınıfı somut bir sınıf olan TV sınıfına bağımlıdır. TV bünyesinde meydana gelen her değişiklik doğrudan RemoteControl sınıfını etkileyecektir. Ayrıca RemoteControl sınıfını TV sınıfı olmadan başka bir yerde kullanılması mümkün değildir.

Bu yazıyı PDF dosyası olarak aşağıdaki linkten edinebilirsiniz.


EOF (End of Fun)
Özcan Acar

Liskov Substitution Principle (LSP) – Liskov’un Yerine Geçme Prensibi

Barbara Liskov tarafından geliştirilen bu prensip kısaca şöyle açıklanabilir:

Alt sınıflardan oluşturulan nesneler üst sınıfların nesneleriyle yer değiştirdiklerinde aynı davranışı göstermek zorundadırlar.

LSP’ye göre herhangi bir sınıf kullanıcısı, bu sınıfın alt sınıfları kullanmak için özel bir efor sarf etmek zorunda kalmamalıdır. Onun bakış açısından üst sınıf ve alt sınıf arasında farklılık yoktur. Üst sınıf nesnelerinin kullanıldığı metotlar içinde alt sınıftan olan nesneler aynı davranışı sergilemek zorundadır, çünkü oluşturulan metotlar üst sınıf davranışları örnek alınarak programlanmıştır. Alt sınıflarda meydana gelen davranış değişiklikleri, bu metotların hatalı çalışmasına sebep verebilir. Özellikte bu metotlarda instanceof gibi nesnelerin tipleri arasında kıyaslama yapılmak zorunda kalındığı zaman, LSP prensibi çiğnenmiş olur ki, bu alt sınıfların varlığından haberdar olunduğu anlamına gelir. Kullanıcı sınıflar ideal durumda alt sınıfların varlığından haberdar bile olmamalıdır.

Resim 1 de yer alan Client sınıfındaki print() metodunun nasıl LSP prensibine ters düştüğünü yakından inceleyelim. Bu metot A sınıfından olan nesneler üzerinde işlem yapmaktadır. A sınıfı B ve C sınıfları tarafından genişletilmiştir, yani A sınıfından olan bir parametre nesnesi aynı zamanda B ve C sınıfında da olabilir.

[source language=’java’]
package shop;

public class Client
{
public void print(A a)
{
if(a instanceof B)
{
((B)a).printB();
}
else if(a instanceof C)
{
((C)a).printC();
}
}

public static void main(String[] args)
{
Client client = new Client();
B b = new B();
C c = new C();

client.print(b);
client.print(c);
}
}

[/source]
Kod 1

Kod 1 de yer alan print() metodu LSP ile uyumlu değildir. Bu metodun A sınıfına bağımlılığı vardır ve bu sınıfın nesneleri üzerinde işlem yapacak şekilde implemente edilmiş olması gerekir. Lakin print() metodu instanceof komutuyla parametre olarak verilen nesnenin hangi tipte olduğunu tespit etmeye çalışmakta ve tipe bağımlı olarak nesne üzerinde işlemi gerçekleştirmektedir. Bu durum hem OCP’ye (Open Closed Principle) hemde LSP’ye ters düşmektedir. OCP uyumlu değildir, çünkü print() metodu A’nin her yeni alt sınıfı için değişikliğe uğramak zorundadır. LSP’ye uyumlu değildir, çünkü B ya da C sınıfından olan nesneler A sınıfından olan bir nesnenin yerini alamadığı için print() metodu instanceof ile nesnenin tipini tespit etmek zorunda bırakılmaktadır. Buradan genel bir sonuç çıkartabiliriz: LSP’ye ters düşen bir implementasyon aynı zamanda OCP’ye de ters düşer.

LSP’nin nasıl uygulanabileceğini diğer bir örnekte görelim. Resim 2 de bir firma çalışanları Personel sınıfını genişleten MaasliPersonel ve ParttimePersonel sınıfları ile temsil edilmektedirler. Personel sınıfı soyuttur (abstract). Çalışanların maaşlarının ödenebilmesi için Personel sınıfında bulunan soyut odeme() metodunun alt sınıflarca implemente edilmesi gerekmektedir. Firmaya yeni stajyerler alındığı için, modelin resim 3 deki gibi adapte edildiğini farz edelim.

Staj yapan elemanlar için maaş ödenmez, bu yüzden odeme() metodu StajyerPersonel sınıfında boş implemente edilmesi gerekir. İmplementasyon şu şekilde olabilir:

[source language=’java’]
public int odeme()
{
return 0;
}
[/source]
Kod 2

Sıfır değerine geri vererek, odeme() metodunun geçerli ve kullanılabilir bir metot olduğunu ifade etmiş oluyoruz. Bu yanlıştır! Bu metodun StajyerPersonel sınıfında implemente edilmemesi gerekir, çünkü staj yapanlara maaş ödenmez.

Bu sorunu kod 3 de yer aldığı gibi bir Exception oluşturarak çözebiliriz. Eğer bir stajyer için odeme() metodu kullanılacak olursa, oluşan PersonelException, bir stajyer için maaş ödenemeyeceğini metot kullanıcısına bildirir. Exception nesneleri olağan olmayan durumları ifade etmek için kullanılır.

[source language=’java’]
public int odeme()throws PersonelException
{
throw new PersonelException(“Stajyer maasli calismaz!”);
}

[/source]
Kod 3

Bu implementasyon ilk örnekte olduğu gibi LSP ile uyumlu değildir. Neden uyumlu olmadığını inceleyelim. Kod 4 de çalışanlara ödenen toplam maaş miktarı hesaplanmaktadır.

[source language=’java’]
List personel = getPersonelList();
int total = 0;
for(int i=0; i < personel.size(); i++) { total+=personel.get(i).odeme(); } [/source] Kod 4 StajyerPersonal sınıfının sisteme eklenmesiyle kod 4 de yer alan kodun değiştirilmesi gerekmektedir. Ya try/catch bloğu kullanılarak oluşabilecek bir PersonelException’in işleme tabi tutulması gerekir ya da metot signatüründe throws kullanılarak PersonelException’in bir üst katmana iletilmesi gerekir. StajyerPersonel ismini taşıyan yeni bir sınıf oluştuğu için, mevcut Personel sınıfı kullanıcıları (client) yapısal değişikliğe uğramıştır. [source language='java'] try { List personel = getPersonelList();
int total = 0;
for(int i=0; i < personel.size(); i++) { total+=personel.get(i).odeme(); } } catch (Exception e) { // handle exception } [/source] Kod 5 [source language='java'] List personel = getPersonelList();
int total = 0;
for(int i=0; i < personel.size(); i++) { if(! (personel.get(i) instanceof StajyerPersonal)) { total+=personel.get(i).odeme(); } } [/source] Kod 6 Try/catch blokları komplike yapılardır ve kodun okunulabilirliğini azaltırlar. Try/catch bloğundan kurtulmak için kod 6 de yer alan implementasyon düşünülebilir. Burada instanceof ile sırada hangi tip bir nesnenin olduğunu tespit edebilir ve StajyerPersonel tipi nesneleri işlem dışı bırakabiliriz. Daha öncede gördüğümüz gibi bu implementasyon LSP ile uyumlu değildir, çünkü üst sınıf ile çalışan bir metot instanceof ile alt sınıfları tanımak zorunda bırakılmaktadır. Bunun tek sebebi StajyerPersonel sınıfından olan bir nesnenin, Personel sınıfından bir nesne ile yer değiştiremez durumda olmasıdır. Personel sınıfını kullanan diğer sınıflar alt sınıf olan StajyerPersonel sınıfı sisteme eklendikten sonra bu değişiklikten etkilenmiştir. LSP’ye göre bu olmaması gereken bir durumdur. Alt sınıfların nesneleri, üst sınıflardan olan nesnelerin kullanıldığı metotlar içinde üst sınıf nesneleriyle aynı davranışı göstermek zorundadırlar, aksi taktirde kullanıcı sınıflar bu durumdan etkilenirler. Sorun staj yapan bir elemanın Personel sınıf hiyerarşisinde yer alan bir sınıf aracılığıyla modellenmiş olmasında yatmaktadır. Staj yapan bir eleman maaş almadığı için personele ait değildir, bu yüzden StajyerPersonel sınıfının Personel sınıfını genişletmesi doğru değildir. Sorunu çözmek ve LSP konform hale gelmek için StajyerPersonel sınıfının Personel sınıf hiyerarşisinden ayrılması gerekmektedir. Bu yazıyı PDF dosyası olarak aşağıdaki linkten edinebilirsiniz. [download id='55']
EOF (End of Fun)
Özcan Acar