Merhabalar arkadaşlar. Önceki derslerimizde Value Change Event ve Apllication Event konularına öğrenmiştik. Bu dersimizler birlikte artık olay yakalama konusunu bitireceğiz.

Application Event Handling bir projesinin yaşam döngüsüne müdahele etmek amacı ile kullanılır arkadaşlar. Açıkçası bu zamana kadar ben Application Event konusu üzerine hiç çalışmamıştım ve görmemiştim. Dolayısı ile anlaması ve anlatması zor bir konu olarak geldi bana.

JSF mimarisi içinde 3 tür uygulama olayı yer alıyor arkadaşlar. Bunlar

PostConstructApplicationEvent:Uygulama başladığı anda gerçekleşmesini istediğimiz durumları tanımlayabildiğimiz olay türüdür.
PreDestroyApplicationEvent:Uygulamaya sona erme komutu geldiğinde uygulama kapanmadan hemen önce yapılacak işleri tanımlayabildiğimiz olay türüdür.
PreRenderViewEvent:Uygulamamızdaki bir sayfa yüklenmeden hemen önce gerçekleşmesini istediğimiz durumları tanımlayabildiğimiz durumdur.
Bu 3 olayı yakalayabilmek için JSF geliştiricileri 2 yol belirlemişler. Birisi Method Binding diğeri ise System Event Listener arabirimi ve faces-config.xml dosyası kullanarak.

Şimdi olayı daha iyi kavrayabilmek için örnek projemizin üzerinden inceleyelim.

index.xhtml Kodu



HTML-Kodu:
html Kodu

<?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://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>JSF Application Events</title>
    </h:head>
    <h:body>
        <h:form>
            <f:event listener="#{userData.isAdmin}" type="preRenderView" />
            <h1>Projenin Ana Sayfası</h1>
        </h:form>
    </h:body>
</html>

Index sayfamız yüklenirken f:event etiketi devreye giriyor ve kendisinin listener özelliğine atanmış metodu çaığırıyor. Bı sırada bu metodun ne zaman çağırılacağını type özelliğinden anlıyor ve sayfa yüklenmeden hemen önce bu metodu (isAdmin) çağırıyor.

UserData.java Kodu



Kod:
import java.io.Serializable;
import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;

@ManagedBean(name = "userData")
@SessionScoped
public class UserData implements Serializable {

private static final long serialVersionUID = 1L;
  
   private String veri = "Başlangıç Değeri";
	
   public void isAdmin(ComponentSystemEvent event){
	veri="PreRenderView İle Değer Atandı";
	FacesContext fc = FacesContext.getCurrentInstance();
		
	if (!"admin".equals(fc.getExternalContext().getSessionMap().get("role"))){

		ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler) fc.getApplication().getNavigationHandler();
		
		nav.performNavigation("access-denied");
	}		
  }	

    public String getVeri() {
        return veri;
    }

    public void setVeri(String veri) {
        this.veri = veri;
    }


}


UserData sınıfımız içindeki isAdmin metodu javax.faces.event paketi altında yer alan ComponentSystemEvent sınıfı türünde bir parametre alıyor. Bu parametre bunun bir yaşam döngüsü sırasında çağırılacak metot olduğunu bildirir. Metot içinde veri adındaki sınıf değişkenine yeni değer atanıyor. Bu da sayfa yüklenirken bu metodun çaığırıldığını gösteren başka bir örnek. Metot projenin sistemi içinde role adındaki bir parametreyi arıyor ve bulursa istenilen sayfaya girmeye izin veriyor. Bulamaz ise isteğin reddildiği sayfaya yönlendiriyor.

CustomSystemEventListener.java Kodu



Kod:
import javax.faces.event.AbortProcessingException;
import javax.faces.event.PostConstructApplicationEvent;
import javax.faces.event.PreDestroyApplicationEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
 
public class CustomSystemEventListener implements SystemEventListener {
 
   @Override
   public boolean isListenerForSource(Object value) {
      return (value instanceof Application);
   }
 
   @Override
   public void processEvent(SystemEvent event) throws AbortProcessingException {
      if(event instanceof PostConstructApplicationEvent){
         System.out.println("Uygulama Başladı! PostConstruct Olayı Tetiklendi");
      }
      if(event instanceof PreDestroyApplicationEvent){
         System.out.println("PreDestroy Olayı Tetiklendi! Uygulama Sona Erdi");
      }
   }
}


Bu sınıfımız içinde önceki ValueChangeEvent ve ActionEvent derslerimizden hatırlayacağınız üzere benzer bir iş yapıyoruz bir ara birim (interface) kullanıyoruz. Bu arabirim içindeki processEvent metodu bizim yaşam döngüsü içinde bazı noktaları yakalama müdahele etme şansı veriyor. Örneğin birinci if koşulunda olayın bir PostConstruct olayı olup olmadığına bakılıyor ve yakalanırsa PostConstruct olayının tetiklendiğini söylüyor. İstersek burada PostConstruct olayı tetiklendiği anda başka bir metot çağırımı vs. yapabiliriz. Benzer şekilde olay bir PreDestroy olayı yani uygulama kapanmadan hemen önce meydana gelen bir olay olursa uygulamanın sona erdiğini loglara yazdırıyoruz.

access-denied.xhtml Kodu



Kod:
<?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://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Erişim Engellendi!</title>
    </h:head>
    <h:body>
        <h1>Erişim Engellendi!</h1>
        #{userData.veri}
    </h:body>
</html>


Bu sayfamız içinde sadece erişim engellendiğine dair bir mesaj ve UserData sınıfı içindeki veri değişkeninin tuttuğu değer yazdırılıyor.

faces-config.xml Kodu



Kod:
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
              xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schema********="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
    <application>
      <!-- Application Startup -->
      <system-event-listener>
         <system-event-listener-class>
            CustomSystemEventListener
         </system-event-listener-class>
         <system-event-class>
            javax.faces.event.PostConstructApplicationEvent
         </system-event-class>    					
      </system-event-listener> 
      <!-- Before Application is to shut down -->
      <system-event-listener>
         <system-event-listener-class>
            CustomSystemEventListener
         </system-event-listener-class>
         <system-event-class>
            javax.faces.event.PreDestroyApplicationEvent
         </system-event-class>    					
      </system-event-listener>
   </application>
</faces-config>


faces-config.xml kodumuz içinde javax.faces.event.PostConstructApplicationEvent ve javax.faces.event.PreDestroyApplicationEvent sınıflarımızı tanıtıyoruz ve kendi yazdığımız yakalayıcı sınıfımızı tanıtıyoruz.



Ekran Çıktıları






Proje çalıştığı anda f:event etiketi devreye girdi ve kendine atanan isAdmin metodu çalıştı. O metot da role adında parametre bulamadığı için erişim engellendi sayfasına yönlendirdi bizi.

Uygulama yüklenirken bir PostConstruct olayı tetiklenmiş. Bu da bize verildi.
Uygulama yüklenirken bir PostConstruct olayı tetiklenmiş. Bu da bize verildi.3.satıra dikkat edelim.

Uygulamayı sunucudan kaldırdığımda (undeploy) loga uygulamanın sonlandırıldığı yazıyor.
Uygulamayı sunucudan kaldırdığımda (undeploy) loga uygulamanın sonlandırıldığı yazıyor.

Bu yazıda da bu kadar arkadaşlar. Olay yakalama konusunu bu şekilde bitiriyoruz. Bu Application Event konusu uygulama sisteminde yaşanacak sorunları yakalamak içinde kullanılabilir ayrıca. Sunucuda hata meydana gelmesi, uygulamanın aniden devre dışı kalması vs. gibi durumlarda.