www.fatihkabakci.com

Personal Website and Computer Science TUR EN

JAVA MIMARISIYLE KURUMSAL COZUMLER

JAVA MIMARISIYLE KURUMSAL COZUMLER
Last update: 7/16/2015 5:11:00 PM

Çözümleyen: Fatih KABAKCI

Bölüm 1 - GİRİŞ ve AMAÇ

Bu bölümde kitabın kapsamını açıkladığından soru bulunmamaktadır.

Bölüm 2 - KURUMSAL JAVA' YA GİRİŞ

2.1) J2EE web uygulamalarını yöneten, içerisinde bir çok standart ve teknoloji barındıran bir kurumsal yazılım platformudur. Standart Java herkes için kullanılabilen bir programlama dilidir ancak J2EE, J2SE' yi de içerisinde barındıran, kurumsal firmaların yazılım çözümleri için geliştirilmiş bir yazılım platformudur.

2.2) Öncelikle bir şartname anlamına gelen JCP komitesi tarafından yürütülen bir JSR(Java Specification Request) oluşturulur. Oluşturulan bu şartnamenin standardı için RI(Reference Implementation) yaratılır. Bu standart' ın onayı ve test edilme işlemleri için TCK(Technology Compatibility Kit) tarafından denetlenir. Son aşamada yönetim tarafından EC(Executive Committee) onaylanarak yeni bir teknoloji üretilmiş olur.

2.3) J2EE teknolojisi

Client Tier
Web Tier
Business Tier
Enterprise Information System Tier

olmak üzere 4 katmandan oluşur. İstemci katmanı, basit bir tarayıcı, applet veya herhangi bir istemci programı olabilir. Web katmanı bir Servlet, JSP veya JSF bileşeni olabilir. İş katmanı EJB veya Spring bileşeni olabilir. Veri katmanı ise MySql, Oracle gibi veritabanı teknolojilerinden biri olabilir.

2.4) Temel amaç kod karmaşıklığını azaltarak, yazılan modüllerin belirli bir sistem içerisinde yapısallığını sağlamaktır. Böylelikle yazılan modüller daha anlaşılır, daha sade ve bakım yapılabilir olacaktır.

2.5) Model veri ve veritabanını temsil eder. Aynı zamanda bu verileri kullanan nesnelerin tümü de model kapsamında değerlendirilir. View ise verilerin kullanıcı tarafında nasıl temsil edileceği ile ilgilidir. GUI ve arayüzler buna birer örnektir. Controller ise hem model hem de view arasındaki tüm mantıksal ve fiziksel işlerin yapıldığı bileşendir. Controller iş mantığını içeren, veri ve ekran arasındaki işlemlerin yapıldığı mantıksal parçadır.

2.6) Proje maliyetini azaltmak en büyük amacıdır. Yazılımcılara sadece ihtiyaç duyduğu platformu ve API' leri sağlar.

2.7) Servlet, JSP ve JSF sınıfları için Web Konteynere, Enterprise Bean' ler için var olan EJB Konteyner' i J2EE' nin 2 konteyneri arasında yer alır. Applet ve Application Client Container ise diğer istemci taraflı konteynerler arasında olarak kabul edilir.

Bölüm 3 - JPA (Java Persistence API)

3.1) Programlama paradigması olan OOP (Object Oriented Programming) ile veritabanı paradigması olan RDMS (Relational Database Management System) arasındaki bağı kurmak amacıyla geliştirilen bir modeldir. Temel amacı yazılımcıya, sadece kodlama tarafına odaklanmasını söyleyip, veritabanı tarafını bir ölçüde soyutlayarak performansı arttırmaktır. Özetle yazılımcıya sadece işi olan kod tarafına yöneltip, veritabanı işlemleri için ekstra efor harcamasını minimize etmeye çalışmasıdır. Bunun yanında yazılımcı, SQL spesifik kodları programı içerisinde kullanma zorunluluğundan kurtulur ve veritabanı programlaması kod tarafından soyutlanmış olur.

3.2) Veritabanındaki nesnelere map edilen Java nesnelerine denir. Bu nesneler çoğunlukla veritabanındaki tablolara karşılık gelir. Java tarafındaki bu nesneler klasik Java nesnelerinden farksız, new operatörü ile oluşturulur. Ardından yapılacak persist(), remove(), clear() gibi her işlem bir transaction mekanizması içine alınır. begin() ve commit() arasındaki her çağrı aktif bir şekilde işletilir. Şayet bir hata oluşursa, rollback() çağrısı ile işlemler geri alınır. Burada en önemli nokta Entity nesnesinin veritabanına fiziksel aktarımı commit() ile sağlanmasıdır. Bu RAM bellekte yaşayan Entity' lerin fiziksel olarak veritabanına kaydedilmesini sağlar.

3.3) Veritabanı nesneleri arasındaki ilişkinin durumuna göre JPA tarafında @OneToOne, @OneToMany, @ManyToOne ve @ManyToMany notasyonları bu ilişkileri temsil eder. Ayrıca tek yönlü(directional) ve çift yönlü(bidirectional) olmak üzere ilişkinin yönü de ifade edilir. Çift yönlü (bidrectional) ilişkilerde taraflardan birisi mappedBy belirteci ile aynı zamanda ilişki yönünün çift yönde olduğunu söyler. Bunlardan hangisinin seçileceği tamamen fiziksel veritabanında olması gereken iş kurallarına göre belirlenmelidir. Örneğin 1 fotoğrafın birden fazla tipte (jpeg, png, bitmap) fotoğrafı olması gerekiyorsa, aynı zamanda farklı tiplerin farklı fotoğraflar yer alabilmesi mümkün ise, bu durum @ManyToMany bidirectional (çift yönlü) ilişki olarak tanımlanmalıdır. Bu durumu ihtiva eden UML aşağıda gösterilmektedir.

OneToOne Directional

3.4)
- Her sınıf için tek tablo stratejisi (The Single Table per Class Hierarchy Strategy)
- Her sınıf için ayrı tablo stratejisi (The Table per Concrete Class Strategy)
- Kalıtılmış alt sınıflar stratejisi (The Joined Subclass Strategy)

3.5) Sütün kalıtımı: A ve B tabloları ilişkilendirilecek olsun. A tablosu, B tablosunun id' sini yabancı anahtar olarak barındırır. Bu durum 1-1 ilişkilerde tercih edilir.

Tablo kalıtımı: A ve B tabloları ilişkilendirilecek olsun. İlişkilendirme ayrı bir C tablosunda, A ve B tablolarının id' lerinin bulundurulması ile yapılır. Bu durum 1-n, n-1 ve n-n ilişkilerde tercih edilir.

3.6) Bir Entity üzerinde yapılan durum değişikliğini, o Entity' nin ilişkili olduğu diğer Entity' ler üzerinde de yapmasını sağlayan bir operasyon modelidir. Örneği bir Entity veritabanından silinecekse, o Entity' nin ilişkili olduğu diğer Entity' de veritabanından otomatik olarak silinir. Böylelikle iki Entity' yi silen kodun çağrımı yerine, kapsayan ana Entity nesnesinin remove() çağrısı yeterli olacaktır. Bu da yazılımcı tarafında, JPA temel işlemlerinin her defasında yazılma zorunluluğunu ortadan kaldırır. Ayrıca veritabanı takip zorunluluğuna da azaltan bir işlemdir. Örneğin aşağıdaki çağrı her iki nesneyi de veritabanından kaldırır.

em.remove(A);
em.remove(B);

// yerine

em.remove(B); // aynı zamanda A' yı da siler.

3.7) Bu belirteç yalnızca gerekli olduğunda kullanılmalıdır. Bir Entity' nin yalnızca belirli işlemler gerçekleşmesi halinde ilişki olduğu nesneyi etkilemesi gerekir. Bunun gerekli gereksiz tüm işlemlerde etkin olması, lüzümsuz yere SQL komutlarının JDBC tarafında işletilmesi anlamına gelir. Özellikle büyük hacimli nesnelerde ekstra yapılan SQL sorguları zaman kayıplarına yol açabilir. Bu yalnızca JPA tarafının değil, aynı zamanda kullanılan Veritabanı yönetim sisteminin de, sorguları nasıl işlettiğine bağlı olarak değişir. Performansı bir ölçüde paylaşan JPA ile birlikte kullanılan veritabanı yönetim sistemidir.

Bölüm 4 - EJB (Enterprise Java Beans)

4.1) Bir gereksinimin karşılanması için yapılan bir takım eylemler o işin mantığını oluşturur. Kurumsal uygulamaların karmaşık gereksinimlerine çözüm getirebilmesi için MVC, üç katman, dört katman, n katman mimarilere ihtiyaç duyar. En basit üç katmanlı mimaride bile sunum, iş ve veri katmanları birbirlerinden ayrılmalıdır. Bu projenin bakımı ve devamlılığı için çok önemli bir yer tutar. Bu sebepten ötürü Java EE, iş mantığını sunum ve veri katmanından ayıran EJB teknolojisini geliştirmiştir.

4.2) Sunum katmanı (Presentation Layer) ile Kalıcılık katmanı (Persistence Layer) arasındadır.

4.3) Her ikisi de belirli bir kullanıcıya atanmaz, durum (state) takibi yapılmaz.

4.4) Bu türde ki EJB nesnelerini sürekli kullanmak RAM bellek üzerindeki yükü arttırır ve sistemin cevap veremez hale gelmesine sebebiyet verir. Çünkü bu tür EJB bean' leri kullanıcı verilerini tutar ve durum takibi yapar. Her iş mantığı için yüklü kullanıcı verileri taşıyan bean' ler oluşturmak, bellek kapasitesini sınırlayabilir.

4.5) Aşağıdaki programda genellikle web sayfalarında yapılan subscription (abone olma) işleminden örnek verilmektedir. Loglama basitlik adına konsol ekranına bastırılmaktadır.

Kullanılan araçlar:

Application Server: JBOSS
IDE: Eclipse Indigo
Operating System: Windows 7 - 64 bits

Yukarıda kullanılan araçlar bir örnektir. Aşağıda verilen uygulamaları dilerseniz farklı bir platformda da deploy ederek çalıştırabilirsiniz.

1. ilk olarak Eclipse ortamında File -> New altından yeni bir Enterprise Application Project oluşturun.

eclipse new ear project

Burada proje adı SubscriptionEAR verilmiştir. Hedef platform ise JBOSS' dır. Siz farklı bir IDE veya application server da kullanabilirsiniz.

eclipse ear project

2. ikinci olarak Eclipse ortamında File -> New altından yeni bir EJB Project oluşturun.

eclipse new ejb project

Burada proje adı SubscriptionEJB verilmiştir. Hedef platform ise JBOSS' dır. Siz farklı bir IDE veya application server da kullanabilirsiniz.

eclipse ejb project

EJB projenizi yukarıdaki gibi oluştururken EAR projenize bağladığınızdan emin olun. Bu şekilde yaparsanız Interceptor konfigurasyon ayarlamalarınızı Eclipse sizin yerinize yapacaktır.

Daha sonra Interceptor görevi gören SubscriptionAspect sınıfı EJB projesi içerisinde tanımlanır. Aşağıdaki programda basitçe konsol ekranına, ilgili metodun ne zaman ve hangi tarihte kesime uğradığı loglanmaktadır.

SubscriptionAspect Sınıfı

package com.fatihkabakci;

import java.lang.reflect.Method;
import java.util.Date;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 4 - EJB (Enterprise Java Beans)
 * Soru 4.5 cozum - SubscriptionAspect sinifi
 * 
 * @author www.fatihkabakci.com
 */
public class SubscriptionAspect {

   @AroundInvoke
   public Object log(InvocationContext context) {
      try {
         System.out.println("[INFO]: SubscriptionAspect -> log start");
         Method method = context.getMethod();
         Date date = new Date();
         System.out.println("[INFO]: SubscriptionAspect -> The method: " + method.getName() + " was intercept on " + date);

         return context.proceed();
      }
      catch (Exception e) {
         System.err.println(e.getMessage());
         return null;
      }
   }
}

Aşağıda ise kesime uğratılacak SubscriptionBean adlı EJB sınıfı verilmektedir. subscribe() metodu, bir kullanıcının web sayfa içeriğine abone olduğunda kesime uğratılarak SubscriptionAspect sınıfının çalışacağını bildirir.

SubscriptionBean Sınıfı

package com.fatihkabakci;

import javax.ejb.Stateless;
import javax.interceptor.Interceptors;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 4 - EJB (Enterprise Java Beans)
 * Soru 4.5 cozum - SubscriptionBean sinifi
 * 
 * @author www.fatihkabakci.com
 */

@Stateless
@Interceptors(SubscriptionAspect.class)
public class SubscriptionBean {
   public void subscribe(String email) {
      System.out.println("[INFO]: SubscriptionBean -> The " + email + " has subscribed");
   }
}

3. yukarıdaki sınıfların inşasından sonra, üçüncü olarak uygulamamızın somut örneğini gerçeklemek adına File -> New altında yeni bir Dynamic Web Project oluşturun.

eclipse new dynamic web project

Projenin adı Subscription olarak verilmiştir ve EAR projesine bağlanmıştır.

eclipse dynamic web project

Bir bağlam olarak da, uygulama projesinin EJB projesine bağlantısı gerekir. Bunun için Subscription projesinde Properties -> Deployment Assembly -> Add ile açılan pencereden Project seçip,

eclipse dynamic web project depassprojectconf

aşağıdaki gibi daha önceden oluşturulan EJB projelerinizi seçerek Finish' e tıklayınız. SubscriptionEJBClient projesini siz oluşturmasanız da SubscriptionEJB projesini oluştururken Eclipse sizin yerinize otomatik olarak oluşturmuştur.

eclipse dynamic web project depassdirconf

EJB sınıflarınıza web projenize ekledikten sonra aşağıdaki Apply ve OK butonlarına basarak projenizin konfigürasyon ayarlarını etkinleştirin.

eclipse dynamic web project depassemblyconf

Bu noktadan sonra artık uygulamayı test edebilecek haldedir. Aşağıda SubscriptionServlet adında bir Servlet sınıfı verilmektedir. Bu sınıf aldığı email url parametresini bean sınıfının subscribe() metoduna argüman olarak vererek Interceptor işleminin harekete geçirilmesine yol açar.

SubscriptionServlet Sınıfı

package com.fatihkabakci;

import java.io.IOException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 4 - EJB (Enterprise Java Beans)
 * Soru 4.5 cozum - SubscriptionServlet sinifi
 * 
 * @author www.fatihkabakci.com
 */
@WebServlet("/SubscriptionServlet")
public class SubscriptionServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;

   /**
    * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    */
   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      try {
         System.out.println("[INFO]: SubscriptionServlet -> has started");
         String email = request.getParameter("email");
         if (email != null) {
            System.out.println("[INFO]: SubscriptionServlet -> received an email: " + email);
            InitialContext ic = new InitialContext();
            SubscriptionBean bean = (SubscriptionBean) ic.lookup("java:global/SubscriptionEAR/Subscription/SubscriptionBean!" + "com.fatihkabakci.SubscriptionBean");
            bean.subscribe(email);
         }
      }
      catch (NamingException e) {
         e.printStackTrace();
      }
   }
}

4. Buraya kadar yukarıdaki tüm adımları yapıldığı takdirde aşağıdaki sorguyu tarayıcınız üzerinde çalıştırın. Tabi JBOSS' u ya da kendi uygulama sunucunuzu başlatmayı unutmayın.

http://localhost:8080/Subscription/SubscriptionServlet?email=info@fatihkabakci.com

Gerekli sorguyu yaptığınızda konsol ekranınızda aşağıdaki logları göreceksiniz. Burada öncelikle SubscriptionServlet sınıfı çalışarak kullanıcıdan gelen email bilgisini alır. Ardından bu bilgiyi esas işin yapıldığı SubscriptionBean sınıfına gönderir. Ancak tam bu esnada SubscriptionAspect sınıfı ayağa kalkarak gerekli loglamayı yapar. Ardından SubscriptionBean sınıfı çalışır ve kullanıcıyı temsili olarak sisteme subscribe eder.

05:20:49,187 INFO  [stdout] (http--127.0.0.1-8080-1) [INFO]: SubscriptionServlet -> has started

05:20:49,189 INFO  [stdout] (http--127.0.0.1-8080-1) [INFO]: SubscriptionServlet -> received an email: info@fatihkabakci.com

05:20:49,206 INFO  [stdout] (http--127.0.0.1-8080-1) [INFO]: SubscriptionAspect -> log start

05:20:49,207 INFO  [stdout] (http--127.0.0.1-8080-1) [INFO]: SubscriptionAspect -> The method: subscribe was intercept on Sat Jul 11 05:20:49 EEST 2015

05:20:49,207 INFO  [stdout] (http--127.0.0.1-8080-1) [INFO]: SubscriptionBean -> The info@fatihkabakci.com has subscribed

4.6) stateless ve singleton türleri bulunur.
Kullanıcı verilerini saklayarak her bir kullanıcıya özel atanmış durum takibi yapan Stateful Bean
Belirli sayıda uygulama sunucusu içerisinde önceden yaratılmış ve her kullanıcının kullanabildiği, durum takibi yapmayan Stateless Bean
Tüm kullanıcıların ortak paylaşımına sunulmuş Singleton Bean

4.7) @PostConstruct, @PreDestroy, @PrePassivate ve @PostActivate bildirimleri sırasıyla bir bean' nin yaratıldıktan sonra, sonlandırılmadan önce, pasif duruma geçerken ve aktif duruma geçtikten sonra olabilecek eylemlerin tasarlandığı metotlar yardımıyla yapılabilir.

4.8) Soru 4.7 de belirten bildirimlerin, EJB sınıfları içerisinde deklare edilen metotların başına getirilerek, ilgili olaylar sırasında bean' lerin takibini ve kontrolünü sağlama amaçlı kullanılır.

4.9) AOP paradigmasında bulunan cross cutting concerns işlemlerinin her biri, iş katmanı içerisinde yer almak zorunda kalırdı. Bunun anlamı, iş katmanı ile doğrudan iş katmanı ile alakalı olmayan kodların bir arada bulunması ve dolayısıyla bakım ve geliştirmenin zorlaşması anlamına gelirdi. Temel amacın yardımcı işler ile ana işlerin birbirinden ayrılmasını sağlayarak, uygulama geliştirmeyi daha sistematik bir yapıda sağlamaktır.

Bölüm 5 - JSF (JavaServer Faces)

5.1) FacesServlet, Renderers, Pages (xhtml, jsp, xul), Converters, Validators, JSF Managed Beans.

5.2) Converter' lar JSF ön yüz ile managed bean arasındaki tip dönüşümünü gerçekleyen bileşenlerdir. Bu dönüşüm kullanıcın girdiği string verileri integer, float, char, short gibi türlere otomatik olarak JSF tarafından yapılan işlemler bütünüdür. Bazı veri türleri içinde (date, time vb) JSF geliştiricisinin belirlediği özel dönüşüm kuralları tanımlanabilir.

Validator' lar ise girilen verilerin istenen kısıtlar altında olup olmadığını denetlemek için kullanılan bileşenlerdir. Örneğin karakter uzunluğu, harf & rakam kontrolü gibi işlemler bu kapsamda kullanılır.

5.3) Postback JSF mimarisinde 2 numaralı olaya, yani Apply Request Values evresine karşılık gelir. Bu evrede kullanıcı bir form verisini sunucuya postalar. Bunu HTTP GET veya POST ile yapabilir. JSF kullanıcıdan ilk kez aldığı verileri bu evrede değerlendirir.

5.4) Bu notasyon uygulama sunucusu açıkken tüm istemcilerin kullanımına sunulur. Her seferde gerekli gereksiz kullanımı ve paylaşımı kaynak problemlerine neden olabilir.

5.5) Kullanılan araçlar:

Application Server: JBOSS
IDE: Eclipse Indigo
Operating System: Windows 7 - 64 bits

Yukarıda kullanılan araçlar bir örnektir. Aşağıda verilen uygulamaları dilerseniz farklı bir platformda da deploy ederek çalıştırabilirsiniz.

1. ilk olarak Eclipse ortamında File -> New altından yeni bir Dynamic Web Project oluşturun.

eclipse dynamic web project

Bu örnekte proje ismi olarak LoginFaces adı verilmiştir. Siz farklı bir isim de verebilirsiniz.

eclipse login faces project

Projeyi oluşturduktan sonra, JSF özelliğini etkinleştirmek için Properties -> Project Facets kısmından JavaServer Faces seçeğini seçerek OK butonuna basın.

eclipse faces project facets config

Sorunun çözümünde tasarlanan iki adet .xhtml dosyası bulunmaktadır. Biri kullanıcıların login olabilmesini sağlayan login.xhtml, diğeri de siteye üye olan kullanıcıların esas sayfaya ulaştıkları index.xhtml sayfası. Çözümün basitliği adına database işlemlerine yer verilmemiştir.

login.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html">
<h:head>
    <title>login</title>
</h:head>
<h:body>
    <h:form>
        <h3>Login</h3>
        <h:outputText value="Username" />
        <h:inputText id="username" value="#{login.username}"></h:inputText>
        <br /><br />
         
        <h:outputText value="Password" />
        <h:inputSecret id="password" value="#{login.password}"></h:inputSecret>
        <br /><br />
        
        <h:commandButton action="#{login.login()}"  value="Login"></h:commandButton>
    </h:form>
</h:body>
</html>

index.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
</head>
<body>
<h:form>
    <h1>Hello #{login.username}</h1>
    <h:commandButton action="#{login.logout()}" value="Logout"></h:commandButton>
</h:form>
</body>
</html>

JSF ön yüz bileşenleri yukarıdaki gibidir. Bu bileşenler ile ilişkili bean sınıfı ise aşağıda verilmiştir.

LoginBean Sınıfı
package com.fatihkabakci;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 5 - JSF (JavaServer Faces)
 * Soru 5.5 cozum - LoginBean sinifi
 * 
 * @author www.fatihkabakci.com
 */

@ManagedBean(name = "login")
@SessionScoped
public class LoginBean implements Serializable {
   private static final long serialVersionUID = 1L;

   private String            password;
   private String            username;

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   public String getUsername() {
      return username;
   }

   public void setUsername(String username) {
      this.username = username;
   }

   public String login() {
      if (validate()) {
         HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
         session.setAttribute("username", username);
      }
      return "index";
   }

   public String logout() {
      HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
      session.invalidate();
      return "login";
   }

   public boolean validate() {
      // assumption db query is done 
      return true;
   }
}


Yukarıdaki LoginBean temsili olarak kullanıcının sistemde kayıtlı olmadığını denetler ve kullanıcıya bir oturum atar. Oturum nesnesinin username niteliği ile bu oturuma bir parametre yerleştirir. Bu noktada esas amacımız olan, kimlik denetiminin gerçekleştirildiği LoginPhaseListener adlı dinleyici sınıf, sayfa her render edildikten sonra bu işlemi yapar. Kimlik denetimi yine mevcut bir oturum bilgisinden elde ettiği username niteliği ile arar.

LoginPhaseListener Sınıfı
package com.fatihkabakci;

import java.io.IOException;

import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpSession;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 5 - JSF (JavaServer Faces)
 * Soru 5.5 cozum - LoginPhaseListener sinifi
 * 
 * @author www.fatihkabakci.com
 */
@SessionScoped
public class LoginPhaseListener implements PhaseListener {
   private static final long serialVersionUID = 1L;

   @Override
   public void afterPhase(PhaseEvent event) {
      FacesContext fcontext = event.getFacesContext();
      ExternalContext econtext = fcontext.getExternalContext();
      HttpSession session = (HttpSession) econtext.getSession(false);

      String fromPage = fcontext.getViewRoot().getViewId();
      Object username = null;
      if (session != null) {
         username = session.getAttribute("username");
      }      

      if (username == null && !fromPage.equals("/login.xhtml")) {
         try {
            econtext.redirect("login.xhtml");
         }
         catch (IOException e) {
            e.printStackTrace();
         }
      }
   }

   @Override
   public void beforePhase(PhaseEvent event) {
      // TODO Auto-generated method stub
   }

   @Override
   public PhaseId getPhaseId() {
      return PhaseId.RESTORE_VIEW;
   }
}

RESTORE_VIEW ve afterPhase() ile sayfa her render edildikten sonra, dinleyici sınıfı kimlik denetimi için harekete geçirir. Şayet ilgili kullanıcı için mevcut bir oturum bilgisi yok ise, kullanıcıyı doğrudan login.xhtml sayfasına yönlendirir. Yukarıdaki dinleyici sınıfın yaratılmasından sonra projede etkin bir şekilde yaşaması için faces-config.xml dosyasına aşağıdaki gibi tanımlanması gerekir.

faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">
    
    <lifecycle>
        <phase-listener>com.fatihkabakci.LoginPhaseListener</phase-listener>
    </lifecycle>

</faces-config>

Yukarıdaki oluşumların ardından uygulama çalıştırılabilir hale gelir. JBOSS sunucusunu çalıştırarak tarayıcınıza http://localhost:8080/LoginFaces/faces/index.xhtml yazdığınızda sistem sizi otomatik olarak login sayfasına yönlendirecektir.

eclipse login page

Kullanıcı adı ve temsili olarak şifre bilgisini yazdıktan sonra uygulama index.xhtml sayfasının açılmasına izin verir.

eclipse index page

Logout butonu ile mevcut oturum bilgisi silinir ve tekrardan login sayfasına yönlendirme yapılır.

5.6) xxxx-xxxx-xxxx-xxxx geçerlilik kuralı şekline sahip bir kredi kartı her biri 4 rakam olan, aralarında - (tire) karakteri ile toplamda 16 rakam ve 4 - karakterinden oluşan oluşan bir tanımlayıcı numarasına sahiptir. - (tire) karakteri esasen sayılmaz. Ancak günümüz bankacılık işlemlerinde bu karakterler form girdilerinde sıklıkla tercih edilir. Dolayısıyla soruda verildiği gibi, geçerlilik kuralı xxxx-xxxx-xxxx-xxxx şeklinde olacaktır. Buradaki x 0 ile 9 arasında herhangi bir rakamı temsil eder. Örneğin 1111-2222-3333-4444 bizim için geçerli bir numara olmalıdır. Ancak 111-2222-3333-4444, 1111*2222_333-4444, a32d-2222-3333-4444 ve 1111-2222-3333- gibi ifadeler geçersizdir. Yukarıdaki geçerlilik kuralını Java Pattern sınıfı içerisinde derlediğimizde aşağıdaki kalıbı yazmamız gerekir.

[\\d]{4}-[\\d]{4}-[\\d]{4}-[\\d]{4}

Yukarıdaki pattern de \\d ifadesi 0 ile 9 arasındaki rakamları ihtiva ederken, {4} ifadeleri bunlardan 4 tane olabileceğini, - ifadesi de yazıldığı gibi - karakterini temsil eder. Bu noktada ihtiyacımız olan kullanıcının kredi kartı numarasını dolduracağı .xhtml uzantılı bir form ve arka tarafta validasyon işleminin yapıldığı bir bean sınıfıdır. Siz validasyon işlemini ön yüz tarafında da yapabilirsiniz. Ancak bu sorunun çözümünde kod tarafında yapılması tercih edilmiştir.

CreditCardValidator Sınıfı
package com.fatihkabakci;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 5 - JSF (JavaServer Faces)
 * Soru 5.6 cozum - CreditCardValidator sinifi
 * 
 * @author www.fatihkabakci.com
 */
@FacesValidator("com.fatihkabakci.CreditCardValidator")
public class CreditCardValidator implements Validator {

   @Override
   public void validate(FacesContext arg0, UIComponent arg1, Object value) throws ValidatorException {
      Pattern pattern = Pattern.compile("[\\d]{4}-[\\d]{4}-[\\d]{4}-[\\d]{4}");
      Matcher matcher = pattern.matcher(value.toString());
      if (!matcher.matches()) {
         FacesMessage msg = new FacesMessage("Credit card validation failed.", "Invalid card number.");
         msg.setSeverity(FacesMessage.SEVERITY_ERROR);
         throw new ValidatorException(msg);
      }
   }
}

payment.xhtml Sayfası
<?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39; ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
<h:head>
    <title>payment</title>
</h:head>
<h:body>
    <h:form>
        <h3>Credit Card Validation</h3>
        <h:outputText value="Enter Credit Card Number" />
        <br />
        <h:inputText id="it1" value="xxxx - xxxx - xxxx - xxxx" required="true">
        <f:validator validatorId="com.fatihkabakci.CreditCardValidator"></f:validator>
        </h:inputText>
        <br /><br />
        <h:message for="it1"/><br />
        <h:commandButton value="OK"></h:commandButton>
    </h:form>
</h:body>
</html>

Yukarıdaki sayfa tarayıcı üzerinde çağrıldığında aşağıdaki görüntü elde edilir. Kullanıcı aykırı formatta girdiler ürettiği takdirde Invalid card number. hatasını alacaktır.

Credit Card Validation Page

Bölüm 6 - Spring Framework

6.1) IOC, nesne oluşturma ve yok etme işlemlerinin tümünde nesnelerin yaşam döngüsünün takibinin Spring' in sorumluluğuna bırakır. DI ise, oluşturulan tüm bu nesnelerin birbirleri arasındaki ilişkilerinin ve yönetiminin bir fiil yine Springin sorumluluğunda olduğunu belirtir.

6.2) faces-config.xml dosyasında etiketleri arasında SpringBeanFacesELResolver sınıfının tam adının eklenmesiyle sağlanır.

6.3) 4 aşamada gerçekleştirilir. faces-config.xml dosyasında Spring eklentisinin yapılması, web.xml dosyasında sırasıyla konteyner işlemleri için bir Spring dinleyici sınıf, JSF Servlet' den gelen istekleri dinleyen bir diğer Spring dinleyici sınıf ve son olarak Spring nesnelerinin tanıtıldığı ifadeler eklenir.

6.4) Aşağıdaki UML diyagramı çözümünün şeklini ihtiva eder.

Spring UML Arac Orneği

Yukarıdaki UML diyagramına göre, her bir sınıfın Spring framework dahilindeki tanımlamaları aşağıda verilmiştir.

Arac Arabirimi
package com.fatihkabakci;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 6 - Spring Framework
 * Soru 6.4 cozum - Arac arabirimi
 * 
 * @author www.fatihkabakci.com
 */
public interface Arac {
   public void calistir();
   public void ileri();
   public void sagaDon();
   public void solaDon();
   public void dur();
}

Araba Sınıfı
package com.fatihkabakci;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 6 - Spring Framework
 * Soru 6.4 cozum - Araba sinifi
 * 
 * @author www.fatihkabakci.com
 */
public class Araba implements Arac {

   @Override
   public void calistir() {
      System.out.println("Araba calisiyor");
   }

   @Override
   public void ileri() {
      System.out.println("Araba ilerliyor");
   }

   @Override
   public void sagaDon() {
      System.out.println("Araba saga donuyor");
   }

   @Override
   public void solaDon() {
      System.out.println("Araba sola donuyor");
   }

   @Override
   public void dur() {
      System.out.println("Araba durdu");
   }
}

Traktor Sınıfı
package com.fatihkabakci;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 6 - Spring Framework
 * Soru 6.4 cozum - Traktor sinifi
 * 
 * @author www.fatihkabakci.com
 */
public class Traktor implements Arac {

   @Override
   public void calistir() {
      System.out.println("Traktor calisiyor");
   }

   @Override
   public void ileri() {
      System.out.println("Traktor ilerliyor");
   }

   @Override
   public void sagaDon() {
      System.out.println("Traktor saga donuyor");
   }

   @Override
   public void solaDon() {
      System.out.println("Traktor sola donuyor");
   }

   @Override
   public void dur() {
      System.out.println("Traktor durdu");
   }
}

AracBean Sınıfı
package com.fatihkabakci;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 6 - Spring Framework
 * Soru 6.4 cozum - AracBean sinifi
 * 
 * @author www.fatihkabakci.com
 */
public class AracBean {
   Arac arac;
   
   public AracBean(Arac arac) {
      this.arac = arac;
   }

   public void sur() {
      arac.calistir();
      arac.ileri();
   }

   public void sagaDon() {
      arac.sagaDon();
   }

   public void solaDon() {
      arac.solaDon();
   }

   public void dur() {
      arac.dur();
   }
}

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
version="3.0">
  <display-name>AracFacesSpring</display-name>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
  
   <listener>
      <listener-class>
         org.springframework.web.context.ContextLoaderListener
      </listener-class>
   </listener>
   <listener>
      <listener-class>
         org.springframework.web.context.request.RequestContextListener
      </listener-class>
   </listener>
   
   <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/Beans.xml</param-value>
 </context-param>
   
</web-app>

faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">
    
    <application>
        <el-resolver>
            org.springframework.Web.jsf.el.SpringBeanFacesELResolver
        </el-resolver>
    </application>

</faces-config>

Çıktı:
Araba calisiyor
Araba ilerliyor
Araba saga donuyor
Araba sola donuyor
Araba durdu

Bölüm 7 - Web Servisleri

7.1) HTTP, JSON, JavaScript, JQuery.

7.2) Jersey, Apache CXF, RESTEasy.

7.3) GET, POST, PUT, DELETE.

7.4) HTML5 ile taracıyıların desteğini alması ve sunucu taraflı iş yükünün istemci makinelerde paylaştırılması bu teknolojiyi popüler hale getirmiştir.

7.5) Sorunun çözümünde basit bir maven projesi oluşturulmuştur. Kullanılan proje maven-archetype-quickstart tipidir ve ilgili pom.xml dosyası aşağıda verilmiştir.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.fatihkabakci</groupId>
  <artifactId>JavaJsonConverter</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>JavaJsonConverter</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    
     <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>1.7.1</version>
     </dependency>
    
  </dependencies>
</project>

Dönüşümlerde kullanılan JObject Sınıfı
package com.fatihkabakci.JavaJsonConverter;

import java.util.ArrayList;
import java.util.List;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 7 - Web Servisleri
 * Soru 7.5 cozum - JObject sinifi
 * 
 * @author www.fatihkabakci.com
 */
public class JObject {

   private int          parm1;
   private String       parm2;
   private List<String> parmList;

   public JObject() {
      parm1 = 10;
      parm2 = "Fatih";
      parmList = new ArrayList<String>();
      parmList.add("parm3 x");
      parmList.add("parm4 y");
      parmList.add("parm5 z");
   }

   @Override
   public String toString() {
      return "DataObject [parm1=" + parm1 + ", parm2=" + parm2 + ", list=" + parmList + "]";
   }
}

Java Object To JSON Object
package com.fatihkabakci.JavaJsonConverter;

import java.io.FileWriter;
import java.io.IOException;
import com.google.gson.Gson;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 7 - Web Servisleri
 * Soru 7.5 cozum - JObjectToJson sinifi
 * 
 * @author www.fatihkabakci.com
 */
public class JObjectToJson {
   public static void main(String[] args) {
      JObject obj = new JObject();
      Gson gson = new Gson();
      String jsonData = gson.toJson(obj);
      try {
         FileWriter writer = new FileWriter("src/main/java/com/fatihkabakci/JavaJsonConverter/file.json");
         writer.write(jsonData);
         writer.close();
      }
      catch (IOException e) {
         e.printStackTrace();
      }
      System.out.println(jsonData);
   }
}

JSON Object To Java Object
package com.fatihkabakci.JavaJsonConverter;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import com.google.gson.Gson;

/**
 * Rahman USTA - Java Mimarisiyle Kurumsal Cozumler
 * Bolum 7 - Web Servisleri
 * Soru 7.5 cozum - JsonToJObject sinifi
 * 
 * @author www.fatihkabakci.com
 */
public class JsonToJObject {
   public static void main(String[] args) {
      Gson gson = new Gson();    
      try {
    
         BufferedReader br = new BufferedReader(new FileReader("src/main/java/com/fatihkabakci/JavaJsonConverter/file.json"));
         JObject obj = gson.fromJson(br, JObject.class);
    
         System.out.println(obj);
    
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

Çıktı:
{"parm1":10,"parm2":"Fatih","parmList":["parm3 x","parm4 y","parm5 z"]}


Rahman Ustanın hazırladığı Java EE pratiğine yönelik bu kitabın tüm soruları cevaplandırılmıştır. Umarım kitabı alan herkese faydalı olur.

Çözümler de eksiklik ya da hata olduğunu düşündüğünüz konularda lütfen uyarıda bulunuz.

Başarılar

Fatih KABAKCI

MemberCommentDate:
barbaross
Her chapterin sonundaki sorularin cevaplari zannedersem cok faydali ve pekistirici olmus.
causes of hiv/aids nav-connector.com signs of aids in men
rite aid savings card boomasontennis.com rite aid online coupon
lasix 100mg betamethasone 0.05% dapoxetine 30mg
acyclovir 800mg cipro 500mg fluconazole pill
diflucan 150mg levaquin 500mg dutasteride pill
cialis 2015 coupon read cialis manufacturer coupon
online cialis coupons prescription coupon card coupons for drugs
online cialis coupons blog.suntekusa.com free cialis coupon
losartankalium teva 50 mg losartan pro medicin losartan medical valley
detrola detralex detrol la
nexium 20 nexium esomeprazol nexium iskustva
6/29/2015 4:41:00 PM

Name:


Question/Comment

   Please verify the image




The Topics in Computer Science

Search this site for





 

Software & Algorithms

icon

In mathematics and computer science, an algorithm is a step-by-step procedure for calculations. Algorithms are used for calculation, data processing, and automated reasoning.

Programming Languages

icon

A programming language is a formal constructed language designed to communicate instructions to a machine, particularly a computer. It can be used to create programs to control the behavior of a machine. Java,C, C++,C#

Database

icon

A database is an organized collection of data. The data are typically organized to model aspects of reality in a way that supports processes requiring information.

Hardware

icon

Computer hardware is the collection of physical elements that constitutes a computer system. Computer hardware refers to the physical parts or components of a computer such as the monitor, memory, cpu.

Web Technologies

icon

Web development is a broad term for the work involved in developing a web site for the Internet or an intranet. Html,Css,JavaScript,ASP.Net,PHP are one of the most popular technologies. J2EE,Servlet, JSP,JSF, ASP

Mobile Technologies

icon

Mobile application development is the process by which application software is developed for low-power handheld devices, such as personal digital assistants, enterprise digital assistants or mobile phones. J2ME

Network

icon

A computer network or data network is a telecommunications network that allows computers to exchange data. In computer networks, networked computing devices pass data to each other along data connections.

Operating Systems

icon

An operating system is software that manages computer hardware and software resources and provides common services for computer programs. The OS is an essential component of the system software in a computer system. Linux,Windows

Computer Science

icon

Computer science is the scientific and practical approach to computation and its applications.A computer scientist specializes in the theory of computation and the design of computational systems.