Perşembe, Nisan 05, 2012

Spring 3 @Scheduled ile zamanlanmış görevler

Java ile uğraşanların çoğu zamanlanmış görevleri yerine getirmek için Quartz Apisini kullanmıştır. Bu api ile basit işlerden tutun clustered kompleks yapıdaki bir çok işimizi yapabiliyoruz aslında.

Spring 3 ile bu zamanlanmış görevler daha da basitleştirilerek bize sunulmaya başlandı. Spring 3 bunun için arka tarafta hem Quartz hem de kendi yapısını kullanabiliyor. Bu yazının konusu Spring ile @scheduled annotasyonunu kullanarak basit bir zamanlanmış görevi nasıl yapabileceğimizi göstermektir.
@Service
public class ScheduledJob {

    @Scheduled(fixedDelay = 5000)
    public void process() {   
        //do your job here
        System.out.println("processing job " + new Date());              
    }
}

işte bu kadar basit. yapacağınız tek şey istediğiniz aralıkta veya zamanda çalışacak metodunuzun başına @Scheduled annotasyonunu koymak. Yukarıdaki metod 5 saniyede bir çalışır. bunun aralığını;
@Scheduled(fixedDelay = 5000)  // iş bittikten 5 sn sonra yeni iş tekrar başlar
@Scheduled(fixedRate = 5000)    //iş başladıktan 5 sn sonra yeniş iş başlar
@Scheduled(cron="0 0 1 * * ? ")    //her gece saat 01:00 da çalışır.

şeklinde verebilirsiniz.

@Scheduled annotasyonunun dışında applicationContext.xml dosyasına
<task:scheduler ../>
ekleyerek de zamanlanmış bir iş yapılabilir.

Clustered bir ortamda çalışacaksanız bunun için Spring in henüz bir çözümü yok bildiğim kadarıyla. Ama spring in kullandığı Quartz zaten buna çözüm getiriyor. Quartz bunun için veritabanında lock tablolar oluşturarak ayarlama yapar. Ama benim tavsiyem cluster bir ortamda çalışıyorsanız Quartz ın oluşturacağı bir sürü tablo yerine siz kendiniz db de bir tane tablo oluşturarak lock değerleri koymak ve oradan kontrol etmek. Cluster ortamlar için bildiğim en basit yöntem bu.

cron expression detayları için bakınız: http://www.quartz-scheduler.org/docs/tutorial/TutorialLesson06.html
quartz cluster detayları için bakınız: http://java-x.blogspot.com/2006/12/using-quartz-scheduler-in-cluster.html
Spring 3 Scheduling : http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/scheduling.html

Perşembe, Ekim 07, 2010

"java.lang.OutOfMemoryError: PermGen space" Hatası

Uzun bir aradan sonra tekrar merhaba. Askerden döner dönmez eclipse'imin bana küçük bir hediyesi işte bu hata oldu. Bunu sizinle de paylaşmak istedim.

Birçoğumuz OutOfMemory hatasını çeşitli tiplerde almışızdır. Bunların en sık olanı "Exception in thread "main" java.lang.OutOfMemoryError: Java heap space" hatasıdır ki; Xmx ile belirtilen heap boyutu aşıldığını gösteriyor. Bunun dışında daha az karşılaşılan ve yazımızın konusu olan "java.lang.OutOfMemoryError: PermGen space" hatası var ki bunu anlamak için java Garbage Collection ın nasıl çalıştığını bilmek gerekiyor.

Daha verimli çöp toplama ve optimizasyonu daha iyi yapmak için java memory alanı(Java heap) nesiller halinde yönetilir. GC algoritması her nesil için farklı farklı çalışır. Bunlardan en uzun süre yaşayan nesil yukarıdaki hatayla ilgili olan nesil "Permanent Generation" dır. Bu nesildeki classlar kullanıcı bilgilerini tutan meta-data classlarıdır. Büyük çaplı uyugulamar rahatlıkla bu segmenti doldurabiler.

Sun JVM her neslin tutulduğu segmentin boyutunu ayarlama imkanı verir. Permanent generation ın başlangıç ve maks boyutunu aşağıdaki gibi ayarlayabiliriz.

-XX:PermSize=64m
-XX:MaxPermSize=128m



Kendi sorunumu bu şekilde çözdüm. Eclipse için bunları eclipse.ini dosyasına eklemek yeterli olur.

Ayrıca normal "Exception in thread "main" java.lang.OutOfMemoryError: Java heap space" için aşağıdaki satırları eclipse.ini ye yerleştirmek gerekiyor;

-vmargs
-Xms128m
-Xmx512m


Tip:
Eclipse'in kullandığı argümanları görmek için Eclipse açıkken "Help>>About Eclipse>>Installation details" i takip ederek "Configuration" tabini açıp bakabilirsiniz.

Pazartesi, Şubat 15, 2010

linux livecd ve liveusb hayat kurtarır

Linux hayatımıza girdi gireli windowsun veremediğini vermeye başladı. Birçok dağıtımı bir çok farklı ve özelleştirilmiş bir şekilde bize özgü çözümler üretti. bu yazının konusu linux live cd ve live usb.

livecd kavramı bootable kavramından farklıdır. bootable ı bilirsiniz açıklamaya gerek yok. livecd ise bilgisayarınıza hiç birşey kurmadan linux işletim sistemini cd veya usb den çalıştırmanızı sağlar. dolayısıyla livecd aynı zamanda bootable bir cd dir.

Diyelimki windowsunuz göçtü. bilgisayarı açtığınızda mavi veya kara ekranlardan başka sizi karşılayan bir şey yok. partition yapıp verilerinizin yedeğini de almamışsınız. işte tam buarada linux livecd hızır gibi imdadınıza yetişiyor. takıyorsunuz livecd veya liveusb'inizi bilgisayarınız bütün herşeyiyle açılıp elinizin altına geliyor. artık bütün verilerinizi ister usb ye ister cd ye yazıp yedeğini alabilir veya daha başka işler yapabilrsiniz. hatta çok severseniz linuxu temelli kurup windowsa veda bile edebilirsiniz:)

livecd denince şüphesiz akla ilk olarak SlaX ve ubuntu gelir. Slax ın temeli ilk linux dağıtımlarından olan slackware e dayanır. Her iki dağıtım da hem live cd hemde live usb seçeneğini sunuyor. SlaX boyut olarak daha küçük ve usb versiyonunu internet üzerinden ayrı bir şekilde indirebiliyorsunuz. ama ubuntu yu önce cd ye yazıp ondan sonra cdden başlatıyorsunuz ve bilgisayarı cd ile açıp oradan liveusb oluşturabiliyorsunuz. dolayısıyla Slax daha basit ve erişimi kolay geliyor.

Slaxin livecd veya live usb versiyonu için: http://www.slax.org/get_slax.php

Ubuntu livecd için: http://www.ubuntu.com/getubuntu/download Ubuntu için söylememiz gereken bir nokta varki livecd versiyonu ile normal versiyonu aynı cdde gelir. livecd uyarıları için : https://help.ubuntu.com/community/LiveCD

Slax liveusb oluşturma
Slaxin liveusb versiyonunu http://www.slax.org/get_slax.php?download=tar dan indirip usbnize unzip yapıyorsunuz. bu işlem usb diskinize /slax/ ve /boot/ diye sadece iki tane directory eklemiş olacak. tek bir adım daha kalıyor. windows için bootinst.bat linux için bootinst.sh çalıştırmak. işte bu kadar. usb nizi artık bir bilgisayara takıp bilgisayarı açtığınızda bilgisayar usb üzerindeki linuxtan açılmış olacak. merak etmeyin windowstaki hiçbir dosyanıza veya sisteminize zarar gelmiycek. işiniz bittiğinde bilgisayarı kapatıp usbnizi çıkarın ve windowsa geçin.


Not:dikkat usb nizi bu iş için ayırmanıza gerek yok dosyaları nomal bir dosya gibi usb ye ekliyorsunuz.

Cuma, Kasım 20, 2009

JSF'te PDF Dosya Görüntüleme

Bir önceki kayıtta dosyaları servlet ile nasıl gösterebileceğimizi gösterdik. şimdi de aynı işi standart jsf yapısı içinde nasıl yapacağımıza bakalım. JSF ile pdf dosyası görüntlemek için button veya commandlink kullanabiliriz. ayrı bir sayfada açmak için target="_blank" yapılır.

public void showFile(){
try{
HttpServletResponse response = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
File file = new File(filePath+fileName);
BufferedInputStream input =new BufferedInputStream(new FileInputStream(file), 1024);

response.reset();
response.setContentType("application/pdf");
response.setHeader("Content-disposition", "inline; filename=\"" + fileName + "\"");

BufferedOutputStream output = new BufferedOutputStream(response.getOutputStream(), 1024);
byte[] buffer = new byte[1024] //1KB buffer size
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
output.close();
input.close();
}catch(Exception e){e.printStackTrace();}
}
facesContext.responseComplete();
}


JSP sayfasında yapılması gereken de şöyle bir kod ile çağırmaktır;

<h:commandLink value="Download PDF" action="#{testBean.showFile}" target="_blank" />

java servlet ile dosya görüntüleme

Jsf veya java nın başka bir teknolojisini kullandığımızda servlete ihtiyaç duyduğumuz zamanlar çok olur. Bu durumlardan bir tanesi de veritabanından veya herhangi bir path'ten aldığımız dosyaları uygulama içinde göstermektir. pdf, doc, excel, jpeg gif veya başka herhangi bir dosya türünü bu şekilde servlet içine okuyarak gösterebiliriz. aşağıda jsf de kullanılan buna ilişkin bir örnek var. bu örnekte pdf dosya türü okunmuştur.
public class MyStoredFiles extends HttpServlet implements Servlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Connection conn = null;
ResultSet rs = null;
PreparedStatement pstmt = null;
InputStream is = null;
String fileName="",mimeType="";

String fileid=request.getParameter("fileid");
String tmpPath = System.getProperty("tmpfilepath");
try {
String sql = "select * from storedfiles where fileid=?";
conn = OraManager.getConnection(this);
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, fileid);
rs = pstmt.executeQuery();
if (rs.next()) {
fileName=rs.getString("filename");
mimeType=rs.getString("content_type");
//write it to the temp area
java.io.File file = new java.io.File(tmpPath+fileName);
FileOutputStream fos = new FileOutputStream(file);
is = rs.getBinaryStream("data");
byte[] buffer = new byte[1000];
while (is.read(buffer) > 0) {
fos.write(buffer);
}
fos.close();

BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
// Get image contents.
byte[] bytes = new byte[in.available()];
in.read(bytes);
in.close();

response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "inline;filename=\""+fileName+"\"");

// Write image contents to response.
response.getOutputStream().write(bytes);

}
} catch (Exception e) {
e.printStackTrace();
}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

Bu örnekte link ile gelen paramterelere göre veritabanından dosya çekiyoruz.
Bu servletimzi web.xml de tanımlamamız gerekiyor;
<servlet>
<description></description>
<display-name>MyStoredFiles</display-name>
<servlet-name>MyStoredFiles</servlet-name>
<servlet-class>org.test.servlet.MyStoredFiles</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyStoredFiles</servlet-name>
<url-pattern>/showstoredfile</url-pattern>
</servlet-mapping>


jsp sayfasında görüntüleme is şöyle olabilir;
<h:commandLink value="#{file.name}" 
onclick="javascript:window.open(root_folder+'/showpffile?fileid=#{file.fileId}','popupWindow', 'dependent=yes,menubar=no,toolbar=no,location=no,resizable=1,scrollbars=yes');">
</h:commandLink>

Perşembe, Kasım 05, 2009

jsf de iframe yerine f:subview ile jsp:include kullanmak

iframe çok eski bir teknoloji. kullanıldığında beraberinde bir çok sorun getirebiliyor. onun için iframe kullanmaktan kaçınmak gerekiyor. jsf te iframe yerine f:subview ile jsp:inlcude kullanılabilir. çok basit bir şekilde aşağıdaki gibi kullanılabilir.
parent.jsp
<f:view>
...
<jsp:include page="child.jsp" />
...
</f:view>

child.jsp;
<f:subview id="child">
...
</f:subview>


f:subview yani child sayfasında eğer parent tan farklı bir bean kullanmak gerekirse o beanin request scope olması gerekiyor.

Salı, Ekim 27, 2009

rich:modalPanel ve rich:fileUpload

rich:fileUpload richfaces kütüphanesinde bulunan çok kullanışlı bir component. Fakat sayfa içinde biraz yer kapladığı için bazen modalpanel açıp onun içinde kullanmak gerekebilir.
rich:modalPanel içinde rich:fileUpload kullanmak için rich:modalPanel in form içinde olmaması gerekiyor. aynı zamanda modalpanel'in içinde fileupload'u içeren bir form olması gerekiyor. yoksa fileupload componenti çalışmaz. örnek kullanımı şöyle olabilir;
<h:form id="outform">
...
<a4j:commandButton value="Upload Excel File" id="fileuploadbutton">
<rich:componentControl for="fileuploadpanel" attachTo="fileuploadbutton" operation="show" event="onclick" />
</a4j:commandButton>
...
</h:form>
<rich:modalPanel id="fileuploadpanel" zindex="2000" autosized="true">
<f:facet name="header">
<h:outputText value="File Upload Panel"></h:outputText>
</f:facet>
<h:form id="fileuploadform">
<rich:fileUpload fileUploadListener="#{testBean.fileUploadListener}" acceptedTypes="csv" ontyperejected="alert('you can upload csv files');">
</rich:fileUpload>
...
</h:form>
</rich:modalPanel>

Cuma, Ekim 09, 2009

Java'da ResultSet size(row count) almak

Java'da resultset size ını veren direk bir method yok. Bunun için ResultSeti scrollable yapmamız gerekiyor. Eğer preparedstatement kullanıyorsak aşağıdaki gibi bir şey yapabiliriz.
pstmt = conn.prepareStatement(sqlstr,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
pstmt.setString(1,param)

Eğer statement kullanılıyorsa;
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR _READ_ONLY);

Bundan sonra Resultset table içinde son sona giderek row number alacağız. En sonda da ResultSetteki kayıtlara sırasıyla ulaşmak için cursoru en başa tekrar getiriyoruz.
int countOfRecords = 0;
if (rs != null) {
rs.last();//move cursor to the last record
countOfRecords = rs.getRow();
rs.beforeFirst();//move cursor to the first record
}