Oracle İAS, her oc4j instance'sı için düz metin olarak tuttuğu log dosyasını xml formatında sakladığı log dosyaları gibi yönetmemektedir. XML loglar belirli bir büyüklüğe geldiği zaman backuplanır ve güncel loglar yeni bir dosyaya yazılır. Backup sayısıda belirli bir seviyeye ulaştığında en eskli log dosyası silinir. Bu log dosyası max büyüklüğü ile log dosyası sayısı ayarlanabilir. Bu ayarlar nasıl yapılacağı ile ilgili ayrıntılara http://download.oracle.com/docs/cd/B31017_01/web.1013/b28950/logadmin.htm adresinden erişebilirsiniz.
Managing Text Log Files
It is important to monitor your log files, as text logging does not have any imposed size limits or log rotation capability. If left unchecked, log files will continue to grow and can overrun the disk.
The only way to manage these files is to stop OC4J, remove the files, and then restart OC4J to start the log files over.
Sürekli büyüyen plain text log dosyaları bir yerden sonra artık okunamamaktadır. Bundan dolayı plain text loglarında xml log dosyaları gibi yönetilebilmesi için bir uygulama geliştirdim. Bu uygulama her gece belirli bir saatte ihtiyaç duyulan oc4j instance'larını durdurur, var olan log dosyasının adını 'dosya-adı+bir gün öncenin tarihi' formatında değiştirir ve tekrardan oc4j instance'nı başlatır. Oc4j instance başlarken plain text log dosyasını göremediği için yeni bir tane oluşturur. Uygulama bu sürümünde plain text log dosyasını günlük olarak backuplar, dosya size'na bakmaz. Ayrıca n(bu değer parametre olarak geçilebilir) günden eski log dosyalarınıda siler, böylece log dosyaları yüzünden disk'in şişmesi engellenir.
Şu an bizim ihtiyacımız bu yönde olduğu için PlainTextLogger anlattığım şekilde çalışmaktadır.
PlainTextFileLoggerTask bir ant task'ı olarak çalışmaktadır.
<plainTextFileLogManager fileName='log dosyasının adı' filePath='log dosyasının yeri' fileExtension='log dosyasının uzantısı' maxLogFile='saklanacak dosya sayısı' />
PlainTextFileLoggerTask.java
package dev.log.plaintext;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.tools.ant.Task;
public class PlainTextFileLoggerTask extends Task {
private String fileName;
private String filePath;
private String fileExtension;
private String maxLogFile;
public PlainTextFileLoggerTask() {
if (maxLogFile == null || maxLogFile.equals("1"))
maxLogFile = "3";
}
public void execute() {
try {
File logFile = new File(filePath + "/" + fileName + "." + fileExtension);
//kurulumdan onceki gunun tarihinin alinmasi icin-getDate(-1)
new File(filePath + "/" + fileName + "_" + getDate(-1) + "." + fileExtension).delete();
logFile.renameTo(new File(filePath + "/" + fileName + "_" + getDate(-1) + "." + fileExtension));
logFile.delete();
sil();
} catch (Exception e) {
System.out.println("Bir hata aldım sanki = " + e);
}
}
/**
* eski log dosyalarinin en guncel olanlardan maxLogFile kadarini birakir gerisini siler.
*/
private void sil(){
List unDeleteds = getUnDeleteds();
File dir = new File(filePath);
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
String name = children[i];
if(name.startsWith(fileName)&&unDeleteds.indexOf(name)==-1){
new File(filePath+"/"+name).delete();
}
}
}
private List getUnDeleteds() {
List unDeleteds = new ArrayList();
for (int i = -(Integer.parseInt(maxLogFile)); i < 0; i++) {
unDeleteds.add(fileName+"_"+getDate(i)+"."+fileExtension);
}
return unDeleteds;
}
private String getDate(int kacgunoncesi) {
Calendar clndr = Calendar.getInstance();
clndr.add(Calendar.DAY_OF_YEAR, kacgunoncesi);
String yil = clndr.get(Calendar.YEAR) + "";
String ay = clndr.get(Calendar.MONTH) + 1 + "";
String gun = clndr.get(Calendar.DAY_OF_MONTH) + "";
if (ay.length() == 1)
ay = "0" + ay;
if (gun.length() == 1)
gun = "0" + gun;
return yil + ay + gun;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getFilePath() {
return filePath;
}
public void setFileExtension(String fileExtension) {
this.fileExtension = fileExtension;
}
public String getFileExtension() {
return fileExtension;
}
public void setMaxLogFile(String maxLogFile) {
this.maxLogFile = maxLogFile;
}
public String getMaxLogFile() {
return maxLogFile;
}
5 Ocak 2009 Pazartesi
Veri Tabanı Hatalarını Yakalama
Çalıştığım web projesinde silme ekranlarından veri silerken bazı kayıtlarda "ORA-02292 Constraint violation - child records found" hatası alıyorduk. Ancak hata sonucunda silinemeyen verinin hangi tablolarda ve o tabloların hangi kayıtlarında kullanıldığını bilemiyorduk. Bunun üzerine yaptığım çalışma sonucunda spring, jsf, hibernate ve oracle db bağlamında bir çözüm buldum.
Öncelikle veri tabanı hatasını transaction sonunda yakalayabilmek için spring frame work'un kullandığı TransactionInterceptor yerine ondan extends eden CustomTransactionInterceptor sınıfını yazdım. Bu sınıf transaction ile ilgili işleri TransactionInterceptor'a delege ediyor ve kendisi sadece bir db hatası alınırsa, bu hatayı işleyerek bir wrapper sınıf içinde faces context'te yerleştiriyor.
Hata bilgisi facescontext'te yerleştirildikten sonra CustomTransactionInterceptor hatayı kendisine geldiği biçimde throw ediyor. Hata CustomActionListener tarafından tekrar yakalanıyor. CustomActionListener yakaladığı hatayı inceleyip, db hatası değilse CustomActionListener'dan bahsettiğim notumdaki şekliyle çalışıyor. Ancak bir db hatası olduğuna karar verirse, hatayı aynı şekilde session'a koyar ancak bu sefer başka bir hata sayfasına yönlenir.
Eğer hata yazılan jsf sayfasının pagecode'undan yakalanıp, modüle özgü bir hata mesajı yayınlanıyorsa, bu durumda hata sayfasına yönlenme olmamaktadır. Çünkü CustomActionListener'a hata gelmemektedir. Bu durumda sayfada gösterilen mesajda 'detay' butonu gösterilmektedir. Bu butona basıldığında ilgili hata sayfasına yönlenme gerçekleşmektedir. Ancak hata pagecode'da yakalanmıyorsa o durumda direk hata sayfasına yönlenir. 'detay' butonunun gözükmesi içinde MessagesRenderer extends edilip CustomMessagesRenderer yazılmalıdır. ve tabi her jsp'yede bu mesaj tag'i konmalıdır.
Yukarıda hatanın nasıl yakalanıp sunulduğu anlatılmıştır. Şimdi ise hatanın detay bilgisinin nasıl elde edildiği anlatılacaktır. "ORA-02292" kodlu oracle db hatasından contraint name,şema adı elde edilmektedir. Veri tabanının sistem sorguları kullanılarak constraint adı ile constraint'in detay bilgisi elde edilir. Ayrıca silinemeyen kaydın eldeki constraint dışındaki silinememeye yol açacak olan diğer constraint'leride elde edilir. Böylece veriyi sildirmeyen tablolar elde edilir. Ayrıca veriyi sildirmeyen tabloların hangi alan üzerinden silinemeyen verinin tablosuna referans yaptığı elde edilmiş olur. Bu seviyede bir kayıt silinemediğinde kaydın hangi tablolardaki veriler yüzünden silinemediği elde edilir.
Şimdi bir üst seviyeye geçerek silinemeyen kaydı, sildirmeyen tablolardaki hangi kayıtlar yüzünden silinemediğini, bu kayıtların hangi modüllerden girildiği ve bu kayıtları temsil edecek tekil bilgileri elde etmektir. Burada bu bilgilerin elde edilmesinde audit log mekanizmasına ihtiyaç vardır. kayıtların hangi modülden girildiği servis seviyesindeki audit logla, kayıtların(varlık,pojo) kimlik bilgileride varlık seviyesindeki audit logla elde edilir.
Sildirmeyen tablolardaki sildirmeyen kayıtlar, referans alanı ve silinemeyen kaydın idsi ile join yapılarak oluşturulan sorgu ile elde edilebilir. Ancak kayıtların audit mesajlarını elde edebilmek için tablo kayıtları değil o kayıtlara karşılık gelen pojolara ihtiyacımız vardır. Hibernate üzerinden sistemdeki tüm pojoların metadatası elde edilir. bu metadata'da pojoya karşılık gelen tablo bilgisi bulunmaktadır. bütün metadatalar dolaşılarak veriyi sildirmeyen tabloların pojoları elde edilir. Ayrıca pojo alanları ve tablo alanları eşleşmeside metadatadan elde edilir. böylece join işleminde kullanılan alanların pojo karşılıkları kullanılarak oluşturulan hql ile veriyi sildirmeyen varlıklar elde edilir. Bu varlığın böylece kimlik bilgisine erişilir. Varlığın sınıf adı ve id'si kullanılarak servis audit kayıtları üzerinden sorgu yapılarak varlığın hangi modülden girildiğide tespit edilir.
Sonuç olarak bir veri silinemediğinde o veriye referansı olan diğer veriler, bu verilerin ayırt edilmesini sağlayan kimlik bilgileri ve bu verilerin girildiği modüller elde edilebilir.
Ayrıca geliştirdiğim teknik ile diğer bazı oracle hatalarıda işlenmektedir. Ancak uygulamamızda en önemli detaylandırılması gereken hata silme hatasıdır. O yüzden diğer hataların detayına girmeyecem.
CustomTransactionListener'ı devreye sokmak için spring-beans-dev-db.xml dosyası aşağıdaki gibi değiştirildi.
<bean id="transactionInterceptor" class="dev.interceptors.transaction.CustomTransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource" />
</property>
</bean>
Hata alındıktan sonra hata sayfasının açılabilmesi için faces-config'e bir tane navigation rule eklenmelidir.
<navigation-rule>
<navigation-case>
<from-outcome>customDBErrorPage</from-outcome>
<to-view-id>/customDBErrorPage.jsp</to-view-id>
</navigation-case>
</navigation-rule>
CustomTransactionInterceptor.java
package dev.interceptors.transaction;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import dev.utils.OracleExceptionUtils;
public class CustomTransactionInterceptor extends TransactionInterceptor {
public CustomTransactionInterceptor() {
}
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
return super.invoke(invocation);
}
catch (DataIntegrityViolationException dive) {
new OracleExceptionUtils().make(dive);
throw dive;
}
catch (UncategorizedSQLException ucse) {
new OracleExceptionUtils().make(ucse);
throw ucse;
}
catch (Exception e) {
throw e;
}
}
}
Kaydı sildirmeyen kayıtların tablolarını bulan sorgu cümlesi;
select dd.TABLE_NAME as sildirmeyentablo,cc.COLUMN_NAME as referans_sutunu,rc.COLUMN_NAME as silinmeyenverinintablosu_id
from all_constraints ac ,all_constraints dd,all_cons_columns cc,all_cons_columns rc
where ac.CONSTRAINT_NAME='constraint_name' and ac.OWNER='db_name'
and ac.OWNER=dd.OWNER and ac.R_CONSTRAINT_NAME=dd.R_CONSTRAINT_NAME
and cc.OWNER=dd.OWNER and cc.CONSTRAINT_NAME=dd.CONSTRAINT_NAME
and rc.OWNER=dd.OWNER and rc.CONSTRAINT_NAME=dd.R_CONSTRAINT_NAME
Sistemteki tüm pojoların metadata bilgileri;
Collection classMetaDatas = getHibernateTemplate().getSessionFactory().getAllClassMetadata().values();
Ayrıca sildirmeyen kayıt bir varlığın detay kayıtlarından biriyse, bu durumda o kaydın ana kaydını bulup o kaydın kimlik bilgilerini göstermesi içinde bir çalışma yapılmıştır.
Collection collectionMetadatas = getHibernateTemplate().getSessionFactory().getAllCollectionMetadata().values();
collectionMetadatas, sistemdeki her bir pojonun içinde liste olarak tutulan diğer pojonun ilişkilerinin metadasını döner. Böylece datay kayıttan ana kayıt elde edilebilir.
Bu yazıyla ilgili daha detaylı bilgi elde edebilmek için bana mail atabilirsiniz.
Öncelikle veri tabanı hatasını transaction sonunda yakalayabilmek için spring frame work'un kullandığı TransactionInterceptor yerine ondan extends eden CustomTransactionInterceptor sınıfını yazdım. Bu sınıf transaction ile ilgili işleri TransactionInterceptor'a delege ediyor ve kendisi sadece bir db hatası alınırsa, bu hatayı işleyerek bir wrapper sınıf içinde faces context'te yerleştiriyor.
Hata bilgisi facescontext'te yerleştirildikten sonra CustomTransactionInterceptor hatayı kendisine geldiği biçimde throw ediyor. Hata CustomActionListener tarafından tekrar yakalanıyor. CustomActionListener yakaladığı hatayı inceleyip, db hatası değilse CustomActionListener'dan bahsettiğim notumdaki şekliyle çalışıyor. Ancak bir db hatası olduğuna karar verirse, hatayı aynı şekilde session'a koyar ancak bu sefer başka bir hata sayfasına yönlenir.
Eğer hata yazılan jsf sayfasının pagecode'undan yakalanıp, modüle özgü bir hata mesajı yayınlanıyorsa, bu durumda hata sayfasına yönlenme olmamaktadır. Çünkü CustomActionListener'a hata gelmemektedir. Bu durumda sayfada gösterilen mesajda 'detay' butonu gösterilmektedir. Bu butona basıldığında ilgili hata sayfasına yönlenme gerçekleşmektedir. Ancak hata pagecode'da yakalanmıyorsa o durumda direk hata sayfasına yönlenir. 'detay' butonunun gözükmesi içinde MessagesRenderer extends edilip CustomMessagesRenderer yazılmalıdır. ve tabi her jsp'yede bu mesaj tag'i konmalıdır.
Yukarıda hatanın nasıl yakalanıp sunulduğu anlatılmıştır. Şimdi ise hatanın detay bilgisinin nasıl elde edildiği anlatılacaktır. "ORA-02292" kodlu oracle db hatasından contraint name,şema adı elde edilmektedir. Veri tabanının sistem sorguları kullanılarak constraint adı ile constraint'in detay bilgisi elde edilir. Ayrıca silinemeyen kaydın eldeki constraint dışındaki silinememeye yol açacak olan diğer constraint'leride elde edilir. Böylece veriyi sildirmeyen tablolar elde edilir. Ayrıca veriyi sildirmeyen tabloların hangi alan üzerinden silinemeyen verinin tablosuna referans yaptığı elde edilmiş olur. Bu seviyede bir kayıt silinemediğinde kaydın hangi tablolardaki veriler yüzünden silinemediği elde edilir.
Şimdi bir üst seviyeye geçerek silinemeyen kaydı, sildirmeyen tablolardaki hangi kayıtlar yüzünden silinemediğini, bu kayıtların hangi modüllerden girildiği ve bu kayıtları temsil edecek tekil bilgileri elde etmektir. Burada bu bilgilerin elde edilmesinde audit log mekanizmasına ihtiyaç vardır. kayıtların hangi modülden girildiği servis seviyesindeki audit logla, kayıtların(varlık,pojo) kimlik bilgileride varlık seviyesindeki audit logla elde edilir.
Sildirmeyen tablolardaki sildirmeyen kayıtlar, referans alanı ve silinemeyen kaydın idsi ile join yapılarak oluşturulan sorgu ile elde edilebilir. Ancak kayıtların audit mesajlarını elde edebilmek için tablo kayıtları değil o kayıtlara karşılık gelen pojolara ihtiyacımız vardır. Hibernate üzerinden sistemdeki tüm pojoların metadatası elde edilir. bu metadata'da pojoya karşılık gelen tablo bilgisi bulunmaktadır. bütün metadatalar dolaşılarak veriyi sildirmeyen tabloların pojoları elde edilir. Ayrıca pojo alanları ve tablo alanları eşleşmeside metadatadan elde edilir. böylece join işleminde kullanılan alanların pojo karşılıkları kullanılarak oluşturulan hql ile veriyi sildirmeyen varlıklar elde edilir. Bu varlığın böylece kimlik bilgisine erişilir. Varlığın sınıf adı ve id'si kullanılarak servis audit kayıtları üzerinden sorgu yapılarak varlığın hangi modülden girildiğide tespit edilir.
Sonuç olarak bir veri silinemediğinde o veriye referansı olan diğer veriler, bu verilerin ayırt edilmesini sağlayan kimlik bilgileri ve bu verilerin girildiği modüller elde edilebilir.
Ayrıca geliştirdiğim teknik ile diğer bazı oracle hatalarıda işlenmektedir. Ancak uygulamamızda en önemli detaylandırılması gereken hata silme hatasıdır. O yüzden diğer hataların detayına girmeyecem.
CustomTransactionListener'ı devreye sokmak için spring-beans-dev-db.xml dosyası aşağıdaki gibi değiştirildi.
<bean id="transactionInterceptor" class="dev.interceptors.transaction.CustomTransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource" />
</property>
</bean>
Hata alındıktan sonra hata sayfasının açılabilmesi için faces-config'e bir tane navigation rule eklenmelidir.
<navigation-rule>
<navigation-case>
<from-outcome>customDBErrorPage</from-outcome>
<to-view-id>/customDBErrorPage.jsp</to-view-id>
</navigation-case>
</navigation-rule>
CustomTransactionInterceptor.java
package dev.interceptors.transaction;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import dev.utils.OracleExceptionUtils;
public class CustomTransactionInterceptor extends TransactionInterceptor {
public CustomTransactionInterceptor() {
}
public Object invoke(MethodInvocation invocation) throws Throwable {
try {
return super.invoke(invocation);
}
catch (DataIntegrityViolationException dive) {
new OracleExceptionUtils().make(dive);
throw dive;
}
catch (UncategorizedSQLException ucse) {
new OracleExceptionUtils().make(ucse);
throw ucse;
}
catch (Exception e) {
throw e;
}
}
}
Kaydı sildirmeyen kayıtların tablolarını bulan sorgu cümlesi;
select dd.TABLE_NAME as sildirmeyentablo,cc.COLUMN_NAME as referans_sutunu,rc.COLUMN_NAME as silinmeyenverinintablosu_id
from all_constraints ac ,all_constraints dd,all_cons_columns cc,all_cons_columns rc
where ac.CONSTRAINT_NAME='constraint_name' and ac.OWNER='db_name'
and ac.OWNER=dd.OWNER and ac.R_CONSTRAINT_NAME=dd.R_CONSTRAINT_NAME
and cc.OWNER=dd.OWNER and cc.CONSTRAINT_NAME=dd.CONSTRAINT_NAME
and rc.OWNER=dd.OWNER and rc.CONSTRAINT_NAME=dd.R_CONSTRAINT_NAME
Sistemteki tüm pojoların metadata bilgileri;
Collection classMetaDatas = getHibernateTemplate().getSessionFactory().getAllClassMetadata().values();
Ayrıca sildirmeyen kayıt bir varlığın detay kayıtlarından biriyse, bu durumda o kaydın ana kaydını bulup o kaydın kimlik bilgilerini göstermesi içinde bir çalışma yapılmıştır.
Collection collectionMetadatas = getHibernateTemplate().getSessionFactory().getAllCollectionMetadata().values();
collectionMetadatas, sistemdeki her bir pojonun içinde liste olarak tutulan diğer pojonun ilişkilerinin metadasını döner. Böylece datay kayıttan ana kayıt elde edilebilir.
Bu yazıyla ilgili daha detaylı bilgi elde edebilmek için bana mail atabilirsiniz.
4 Ocak 2009 Pazar
JSF'te istisna yakalama
Jsf ile geliştirdiğiniz bir web uygulamasında alınan hataları yakalayıp ortak bir hata sayfasına yönlerdirmek için jsf'in bir sınıfı olan ActionListenerImpl sınıfını extend edip faces-config'e gerekli değişiklikleri yaparak genel bir çözüm üretebilirsiniz.
faces-config.xml'de application taglerinin arasına bir action-listener tanımı koymak gerekmektedir. Böylece jsf artık sizin custom listener'ınızı kullanacaktır.
<application>
<action-listener>dev.action.listeners.CustomActionListener</action-listener>
</application>
Hata alındıktan sonra hata sayfasına yönlendirmek için faces-config'e bir tane navigation rule eklenmelidir.
<navigation-rule>
<navigation-case>
<from-outcome>customErrorPage</from-outcome>
<to-view-id>/customErrorPage.jsp</to-view-id>
</navigation-case>
</navigation-rule>
ve aşağıda hatayı yakalayıp hata sayfasının istediği formata çevirip session koyduktan sonra hata sayfasını açan action listener.
package dev.action.listeners;
import com.ibm.faces.context.MultipartExternalContextImpl;
import com.sun.faces.application.ActionListenerImpl;
import javax.faces.FacesException;import javax.faces.application.Application;
import javax.faces.application.NavigationHandler;
import javax.faces.component.ActionSource;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.event.ActionEvent;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import dev.utils.CustomErrorData;
import dev.constants.Sabitleri;
public class CustomActionListener extends ActionListenerImpl {
public CustomActionListener() {
}
public void processAction(ActionEvent event) {
UIComponent component = event.getComponent();
ActionSource actionSource = (ActionSource) component;
MethodBinding methodBinding = actionSource.getAction();
try {
super.processAction(event);
} catch (FacesException e) {
hataSayfasiniHazirla(e, methodBinding);
}
}
private void hataSayfasiniHazirla(FacesException e, MethodBinding methodBinding){
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ServletException servletException = new ServletException(e.getMessage(), e);
MultipartExternalContextImpl externalContext = (MultipartExternalContextImpl)
context.getExternalContext();
HttpServletRequestWrapper requestWrapper = (HttpServletRequestWrapper)
externalContext.getRequest();
HttpServletRequest httpServletRequest = (HttpServletRequest)
requestWrapper.getRequest();
CustomErrorData errorData = hataSayfasiVeriHazirla(((Throwable) servletException),
httpServletRequest);
HttpSession session = httpServletRequest.getSession(); session.setAttribute
("customErrorData", errorData);
NavigationHandler navigationHandler= application.getNavigationHandler();
navigationHandler.handleNavigation(context, null == methodBinding? null:
methodBinding.getExpressionString(), Sabitler.GENEL_HATA_NAVIGATION);
context.renderResponse();
}
}
ve en son olarak customErrorPage.jsp'yi kodlamak gerekiyor. bu da artık sizin ihtiyaçlarınıza göre şekillenir.
faces-config.xml'de application taglerinin arasına bir action-listener tanımı koymak gerekmektedir. Böylece jsf artık sizin custom listener'ınızı kullanacaktır.
<application>
<action-listener>dev.action.listeners.CustomActionListener</action-listener>
</application>
Hata alındıktan sonra hata sayfasına yönlendirmek için faces-config'e bir tane navigation rule eklenmelidir.
<navigation-rule>
<navigation-case>
<from-outcome>customErrorPage</from-outcome>
<to-view-id>/customErrorPage.jsp</to-view-id>
</navigation-case>
</navigation-rule>
ve aşağıda hatayı yakalayıp hata sayfasının istediği formata çevirip session koyduktan sonra hata sayfasını açan action listener.
package dev.action.listeners;
import com.ibm.faces.context.MultipartExternalContextImpl;
import com.sun.faces.application.ActionListenerImpl;
import javax.faces.FacesException;import javax.faces.application.Application;
import javax.faces.application.NavigationHandler;
import javax.faces.component.ActionSource;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.event.ActionEvent;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import dev.utils.CustomErrorData;
import dev.constants.Sabitleri;
public class CustomActionListener extends ActionListenerImpl {
public CustomActionListener() {
}
public void processAction(ActionEvent event) {
UIComponent component = event.getComponent();
ActionSource actionSource = (ActionSource) component;
MethodBinding methodBinding = actionSource.getAction();
try {
super.processAction(event);
} catch (FacesException e) {
hataSayfasiniHazirla(e, methodBinding);
}
}
private void hataSayfasiniHazirla(FacesException e, MethodBinding methodBinding){
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ServletException servletException = new ServletException(e.getMessage(), e);
MultipartExternalContextImpl externalContext = (MultipartExternalContextImpl)
context.getExternalContext();
HttpServletRequestWrapper requestWrapper = (HttpServletRequestWrapper)
externalContext.getRequest();
HttpServletRequest httpServletRequest = (HttpServletRequest)
requestWrapper.getRequest();
CustomErrorData errorData = hataSayfasiVeriHazirla(((Throwable) servletException),
httpServletRequest);
HttpSession session = httpServletRequest.getSession(); session.setAttribute
("customErrorData", errorData);
NavigationHandler navigationHandler= application.getNavigationHandler();
navigationHandler.handleNavigation(context, null == methodBinding? null:
methodBinding.getExpressionString(), Sabitler.GENEL_HATA_NAVIGATION);
context.renderResponse();
}
}
ve en son olarak customErrorPage.jsp'yi kodlamak gerekiyor. bu da artık sizin ihtiyaçlarınıza göre şekillenir.
3 Ocak 2009 Cumartesi
eski bir alışkanlık... yeniden
ve belkide şiir,
eski bir alışkanlık...
yazmayalı ne kadar oldu acaba, duyguların karanlık bir kuyudan gün ışığına çıkamadığı, tozlanmış masada sararmış kağıtların önünde ifadesiz bir yüzle güçsüz düşmüş ellerin kalemin o hafifletici tadını duymayalı ne kadar oldu acaba. odanın tek penceresinden içeri sızan temiz havanın dolduğu bedende sıkılmış kelimelerin ağırlığı altında kalan şairin, sessizliği bölen kalem hareketlerinin sonuncusu ne zaman havayı yırtmıştı acaba. duvarda kopmayan yapraklarıyla güçlü bir kaleyi anımsatan, yıkılmayan surlarıyla yıllardır kendini savunan takvime sormalı belki. ama hepsi tek bir ruh bu odada. ketumluk tüm canlıların bedenini sarmış. dermansız bir hastalık sanki. yıllar önce herkes bir sessizlik yemini etmişte konuşmuyor. tozların inançlı çürütme savaşına karşın her şey ölümü göze almış sessizlik için. havada kalan sorular yorgun bedenlerini parkelerin üstüne, aralardaki kara deliklerden sonsuzluğa bırakıyor.
ama bir gün şair demir almaya karar veriyor, demir alamayan gemilerin sonuncusuda demir alıyor. ve o şiir yazılıyor, eski bir alışkanlık...
eski bir alışkanlık...
yazmayalı ne kadar oldu acaba, duyguların karanlık bir kuyudan gün ışığına çıkamadığı, tozlanmış masada sararmış kağıtların önünde ifadesiz bir yüzle güçsüz düşmüş ellerin kalemin o hafifletici tadını duymayalı ne kadar oldu acaba. odanın tek penceresinden içeri sızan temiz havanın dolduğu bedende sıkılmış kelimelerin ağırlığı altında kalan şairin, sessizliği bölen kalem hareketlerinin sonuncusu ne zaman havayı yırtmıştı acaba. duvarda kopmayan yapraklarıyla güçlü bir kaleyi anımsatan, yıkılmayan surlarıyla yıllardır kendini savunan takvime sormalı belki. ama hepsi tek bir ruh bu odada. ketumluk tüm canlıların bedenini sarmış. dermansız bir hastalık sanki. yıllar önce herkes bir sessizlik yemini etmişte konuşmuyor. tozların inançlı çürütme savaşına karşın her şey ölümü göze almış sessizlik için. havada kalan sorular yorgun bedenlerini parkelerin üstüne, aralardaki kara deliklerden sonsuzluğa bırakıyor.
ama bir gün şair demir almaya karar veriyor, demir alamayan gemilerin sonuncusuda demir alıyor. ve o şiir yazılıyor, eski bir alışkanlık...
Kaydol:
Kayıtlar (Atom)