Java EE’de Injection Mekanizması

Java EE, nesnelerin instance’larını yaratmadan direk erişilebilmesini sağlayan iki tip injection mekanizması destekler. Sadece gerekli olan kaynaklar ve bağımlı oldukları nesneler annotation‘lar ile belirtilir. Geri kalan tüm iş Container tarafından ele alınır. Bu yazımda kullanılan iki tip Injection ile ilgili bilgiler vermeye çalışacağım :

      1. Resource Injection :

Container tarafından yönetilen ve JNDI ile erişebildiğimiz nesnelere erişmek için kullanılır. Örneğin Servlet sınıfları, Managed Bean’ler, Enterprise Bean’ler ya da sunucuda tanımlanmış olan bağlantı havuzları gibi veri kaynakları.

@Resource annotation’ı kullanılır.

[codesyntax lang=”java5″ lines=”no”]

public class MyServlet extends HttpServlet {
	@Resource(name="java:comp/erkin")
	private Datasource dsc;
	...
}

[/codesyntax]

Benzer bir iş setter metodu tanımlayarak da kullanılabilir.

[codesyntax lang=”java5″ lines=”no”]

public class MyServlet extends HttpServlet {
	private Datasource dsc;
	...
	@Resource(name="java:comp/erkin")
	public void setDsc(Datasource ds) {
		dsc = ds;
	}
}

[/codesyntax]

[box type=”info”] Setter metotlarının mutlaka void dönüş tipi olması, metot isminin set ile başlaması ve tek bir parametre alması gerekir.[/box]

 @Resource annotation’ı type safe olmadığı için dönen nesnelerle atanan nesnelerin tipinin aynı olması gerekir. Aynı olmadığı takdirde çalışma anında hata alırsınız.

     2. Dependency Injection :

Dependency Injection sayesinde normal Java sınıfları, managed nesnelere dönüştürülerek Container tarafından yönetilen başka bir nesne içerisinde kullanılabilir.

@Inject annotation’ı kullanılır. Bu annotation ile belirtilen neesnelerin tüm yaşam döngüleri (yaratılmasından yok edilmesine kadar) Container tarafından yönetilir. Ayrıca Java EE Inject edilen bean’ler için geçerlilik bölgeleri tanımlar. (Scope)

[codesyntax lang=”java5″ lines=”no”]

@RequestScoped
public class CurrencyConverter { ... }

[/codesyntax]

Servlet sınıfı içindeki kod :

[codesyntax lang=”java5″ lines=”no”]

public class MyServlet extends HttpServlet {
    @Inject CurrencyConverter cc;
    ...
}

[/codesyntax]

Resource Injection’a kıyasla Dependency Injection’da nesneler type safe yönetilirler.

Aralarındaki genel farklar :

cdi

Kaynak : http://docs.oracle.com/javaee

JSF 2.x sürümünde AJAX kullanımı

JSP Sayfasında AJAX Kullanımı” başlıklı yazımda AJAX teknolojisinin ne olduğundan ve JSP sayfalarındaki basit kullanımından söz etmiştim. Bu yazımda ise JSF 2 ve üstü sürümlerinde etiketlerimize nasıl AJAX eklediğimizi anlatmaya çalışacağım.

Öncelikle JSF’te hiç JavaScript ve XML bilmeden sayfalarımıza AJAX teknolojisini ekleyebileceğimizi belirtmek isterim.

Bunun için yapmamız gereken birkaç adım var.

  1. XHTML sayfasında <h:head> etiketi kullanılmalıdır. Bu etiketi eklediğimizde sayfamıza jsf.js dosyasını eklemiş oluruz. Bu sayede istekler AJAX isteği olarak gönderilebilir.
  2. Hangi bileşen AJAX isteği yaratacaksa, o bileşen kendi etiketi içerisinde <f:ajax> etiketini kullanmalıdır. Bu sayede hangi bileşenin isteği gönderirken AJAX isteği yarattığı belirtilmiş olur.
  3. Cevap döndükten sonra hangi bileşenlerin güncelleneceğini <f:ajax> etiketinin render özelliğinde söyleriz. Böylece sayfanın tamamı güncellenmez sadece render özelliğinde ID’sini verdiğimiz etiketler güncellenir.

Sadece bu 3 özelliği kullanarak basit bir örnek kod yazalım.

Web sayfamızda sadece bir button olsun. Bu button’a tıkladığımızda 1 ile 10 arasında rasgele bir sayı yaratarak aynı sayfada gösterelim. Ancak sayfamızın tamamı güncellenmeden sadece belirli bir bölgesinin güncellenmesini istiyoruz.

Bunun için sadece güncellenmesini istediğimiz etiketlere birer ID veriyoruz. Sonra da bu ID’leri <f:ajax> etiketinin render özelliğine veriyoruz.

[box type=”info”] Birden fazla bölge (etiket) güncellenecekse render özelliğinde ID’ler araya boşluk bırakılarak yazılır.[/box]

XHTML sayfa kodu aşağıdaki gibi olacaktır.

 

[codesyntax lang=”html4strict” lines=”no”]

<?xml version="1.0" encoding="ISO-8859-9" ?>
<!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:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-9" />
<title>Insert title here</title>
</h:head>
<body>
	<h:form>
		<h:commandButton value="RASGELE SAYI" action="#{bean.rasgele}">
			<f:ajax render="etkilenecekId" />
		</h:commandButton>
		<br/>
		<h:outputText id="etkilenecekId" value="#{bean.sayi}" />
	</h:form>
</body>
</html>

[/codesyntax]

Managed Bean sınıfının kodu da aşağıdaki gibi olacaktır.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.ajax.beans;

import javax.faces.bean.ManagedBean;

@ManagedBean
public class Bean {

	private double sayi;

	public double getSayi() {
		return sayi;
	}

	public void setSayi(double sayi) {
		this.sayi = sayi;
	}

	public String rasgele() {
		setSayi(Math.random() * 10);
		return null;
	}
}

[/codesyntax]

Proje çalıştırdığımızda sayfanın tamamının güncellenmediğini göreceksiniz.

cikti1

cikti2

Struts 2’de Kendi Interceptor Sınıfımızı Yaratmak

Struts 2’de Interceptors sayesinde tüm istekler ve yönlendirmeler üzerinde işlemler gerçekleştirebiliriz. Bir web sayfasından gönderilen parametre Interceptors sayesinde Action sınıfı içerisindeki bir değişkenin değerine set edilir.  Ayrıca action metodumuz (Action sınıfındaki execute() metodu) çalışmadan önce ve sonra yapılacak işler varsa, Interceptors bize bu işleri gerçekleştirme imkanını sağlar.

Interceptors konfigurasyon dosyasında (struts.xml) belirli bir paket tanımı içerisinde tanımlanır. Konfigurasyon dosyalarında tanımladığımız paketleri genellikle struts-default.xml dosyasından extend ederiz. Bu sayede bu dosya içerisinde tanımlanmış tüm özellikleri kullanabiliriz.

[box type=”info”] struts-default.xml dosyası struts2-core-xxx.jar dosyası içerisindedir.[/box]

struts-default.xml dosyası içerisinde de halihazırda tanımlanmış birçok Interceptor vardır. Çoğu uygulama için bu tanımlar yeterli olacaktır.

Interceptor tanımları struts.xml dosyasında basit anlamda aşağıdaki gibi yapılır.

[box type=”warning”] Aşağıdaki tanım struts-default.xml dosyasından örnek olması amacıyla alınmıştır.[/box]

[codesyntax lang=”xml” lines=”no”]

<struts>
   ...
   <package name="struts-default">
      <interceptors>
         <interceptor name="alias"/>
         <interceptor name="autowiring"/>
         ...
      </interceptors>
   </package>
   ...
</struts>

[/codesyntax]

Konfigurasyon dosyasında birden fazla action tanımlanmışsa ve her bir action aynı Interceptor’ları kullanıyorsa, kullanılan Interceptor’lar bir stack tanımı yapılarak referans gösterilir.

[codesyntax lang="xml" lines="no"]
<package name="default" namespace="/" extends="struts-default">
     <interceptors>
        <interceptor-stack name="stack1">
             <interceptor-ref name="timer"/>
             <interceptor-ref name="logger"/>
             <interceptor-ref name="defaultStack" />
        </interceptor-stack>
    </interceptors>

    <action name="login">
        <interceptor-ref name="stack1"/>
        <result name="success">/menu.jsp</result>
    </action>

    <action name="logout">
        <interceptor-ref name="stack1"/>
        <result name="success">/logout.jsp</result>
    </action>
</package>
[/codesyntax]

[box type=”info”] Yukarıdaki örnekte timer, logger ve defaultstack isimli Interceptor’lar struts-default.xml dosyasında tanımlanmışlardır. İsterseniz kendi tanımladığınız Interceptor’ları da bir stack tanımı yaparak action içerisinde referans olarak verebilirsiniz.[/box]

Çok özel uygulamalar için kendi Interceptor sınıflarımızı yazma ihtiyacı duyabiliriz. Bu gibi durumlarda Interceptor sınıflarının nasıl tanımlandığını basit bir örnekle anlatmaya çalışayım.

Projemde kullandığım teknolojiler :

–          JDK 1.7

–          Eclipse Juno 4.2

–          Struts 2.3.8

–          Apache Tomcat 7

CustomInterceptor isminde yeni bir web projesi yaratıyorum.

İlk olarak JSP sayfamı tasarlıyorum.

index.jsp

[codesyntax lang=”html4strict” lines=”no”]

<%@ page language="java" contentType="text/html; charset=ISO-8859-9" pageEncoding="ISO-8859-9"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
	<body>
       		<s:a href="tikla">Interceptor Test</s:a>
	</body>
</html>

[/codesyntax]

Basit bir sayfa ve sadece tek bir link var. Şimdi linke tıkladığımızda çalışacak Action sınıfını tasarlıyorum.

TiklaAction.java

[codesyntax lang=”java” lines=”no”]

package sample;

public class TiklaAction {

       public String execute() {
             System.out.println("Action calisti");
             return "success";
       }
}

[/codesyntax]

Bu sınıf da basit bir POJO ve sadece konsola “Action calisti” yazarak sayfayı yönlendiriyor. Yönlendirilecek sayfayı tasarlayalım.

success.jsp

[codesyntax lang=”html4strict” lines=”no”]

<%@ page language="java" contentType="text/html; charset=ISO-8859-9" pageEncoding="ISO-8859-9"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
	<body>
       		<h1>Yönlendirilen Sayfa</h1>
	</body>
</html>

[/codesyntax]

Şimdi de Interceptor sınıflarımızı tasarlayalım. Bir sınıfın Interceptor olabilmesi için;

1-      Interceptor arayüzünü gerçekleştirmesi gerekir ya da

2-      Interceptor arayüzünü gerçekleştirmiş olan AbstractInterceptor sınıfından türemesi gerekir.

AbstractInterceptor sınıfını kullanıyorsak init() ve destroy() metotlarını ezme zorunluluğumuz kalmaz. Ben iki tane Interceptor sınıfı tanımlayacağım.

MyInterceptor1.java

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.interceptors;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor1 extends AbstractInterceptor {
       private static final long serialVersionUID = -299349963368714122L;

       @Override
       public String intercept(ActionInvocation inv) throws Exception {
             System.out.println("MyInterceptor1 sinifinda action sinifindaki execute metodu calismadan once yapilacak isler");
             String invocationResult = inv.invoke()
             System.out.println("MyInterceptor1 sinifinda action sinifindaki execute metodu calistiktan sonra yapilacak isler");
             return invocationResult;
       }
}

[/codesyntax]

MyInterceptor2.java

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.interceptors;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor2 extends AbstractInterceptor {
                private static final long serialVersionUID = -7461817391953291560L;

                @Override
                public String intercept(ActionInvocation inv) throws Exception {

                               System.out.println("MyInterceptor2 sinifinda action sinifindaki execute metodu calismadan once yapilacak isler");
                               String invocationResult = inv.invoke();
                               System.out.println("MyInterceptor2 sinifinda action sinifindaki execute metodu calistiktan sonra yapilacak isler");
                               return invocationResult;
                }
}

[/codesyntax]

Şimdi de konfigurasyon dosyasını tanımlayalım.

struts.xml

[codesyntax lang=”xml” lines=”no”]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC

       "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
       "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
             <package extends="struts-default" name="myPackage">
                    <interceptors>
                           <interceptor class="com.javauzmani.interceptors.MyInterceptor1" name="myInterceptor1"></interceptor>
                           <interceptor class="com.javauzmani.interceptors.MyInterceptor2" name="myInterceptor2"></interceptor>
                    </interceptors>

                    <action class="com.javauzmani.action.TiklaAction" name="tikla">
                           <interceptor-ref name="myInterceptor1"></interceptor-ref>
                           <interceptor-ref name="myInterceptor2"></interceptor-ref>
                           <result name="success">/success.jsp</result>
                    </action>
             </package>
</struts>

[/codesyntax]

Interceptor’lar konfigurasyon dosyasında tanımlandıkları sırada çalışırlar.

web.xml dosyası aşağıdaki gibidir.

[codesyntax lang=”xml” lines=”no”]

<?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" id="WebApp_ID" version="3.0">

  <display-name>CustomInterceptor</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

</web-app>

[/codesyntax]

Projemizi çalıştırdığımızda index.jsp sayfası gelecektir.

1

Linke tıkladığımızda sayfa success.jsp’ye yönlendirilir.

2

Konsol çıktısı da aşağıdaki gibi olur.

3

Action sınıfları Servlet sınıflarından farklı olarak thread-safe çalışırlar. Gelen her istek için Action sınıfının bir instance’ı yaratılır. Servlet’lerde ise aynı instance gelen her istek için kullanılır.

Fakat Interceptor’lardaki durum farklıdır. Action sınıfları thread-safe olsa da Interceptor’ların instance’ları bir defa yaratılır ve aynı Servlet’ler gibi her istek için kullanılırlar. Bu yüzden Interceptor sınıfları içerisindeki kodların thread-safe yazılması gerekir.

Struts 2’de Sabit Tanımlama (Constant Configurations)

Struts 2 Framework kullanırken uygulama içinde kullandığımız bazı ayarlar sabit değerler ile ayarlanabilir.

Struts’ın konfigurasyon dosyasında tanımlanan constant etiketleri ile framework konfigurasyonları çok basit bir şekilde yapılabilir. Ayrıca Struts ile birlikte kullanılan eklentiler de yine bu sabit değerler sayesinde ayarlanabilir. İki ana rolleri vardır.

  1. Birincisi örneğin yüklenecek maximum dosya boyutu ile standart değer olan 2 MB dışında bir değer verilebilir. Veya geliştirme ortamında çalışan uygulama için daha çok log yazılması basit bir sabit değerle belirtilebilir. Ya da başka bir örnekle kendi oluşturduğumuz tema ismi, bulunduğu dizin ve tip bilgisini tanımlayabiliriz.
  2. İkincisi Bean implementasyonu tanımlanabilir.

Sabitler standartta aşağıdaki sırada uygulama içerisinde aranırlar. Bir sonraki dosyada aynı sabit tekrar tanımlanmışsa ezilmiş olur.

  1. struts-default.xml
  2. struts-plugin.xml
  3. struts.xml
  4. struts.properties
  5. web.xml

Bu dosyalardan ilk 2 tanesi framework içerisinde standart olarak gelir. Diğer dosyaları istersek güncelleyebiliriz.

struts.xml

[codesyntax lang=”xml” lines=”no”]

<struts>
	...
	<constant name="struts.devMode" value="true" />
	<constant name="struts.ui.theme" value="mytheme" />
	<constant name="struts.ui.templateDir" value="template" />
	<constant name="struts.ui.templateSuffix" value="ftl" />
  	...
</struts>

[/codesyntax]

struts.properties

[codesyntax lang="xml" lines="no"]

# Gelistirme modu acik
struts.devMode=true
# Kendi tema ismimiz
struts.ui.theme=mytheme
# Temamizin bulundugu dizi ismi
struts.ui.templateDir=template
# Tema tipi (ftl)
struts.ui.templateSuffix=ftl
[/codesyntax]

web.xml

[codesyntax lang=”xml” lines=”no”]

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="ttp://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" id="WebApp_ID" version="3.0">

    ...
    <filter>
        <filter-name>struts</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
        <init-param>
               <param-name>struts.devMode</param-name>
               <param-value>true</param-value>
        </init-param>
    </filter>
    ...
</web-app>

[/codesyntax]

Struts 2’de .action uzantısını nasıl silerim?

Struts 2’de her bir Action sınıfını çağırmak için standartta .action uzantısı kullanılır. Başka bir deyişle struts.xml dosyasında Action sınıfını çağırmak için tanımlanan ismin sonuna .action yazılarak istek gönderilir. İsmi “LoginAction” olan bir sınıfın çağrım ismi “login” olarak tanımlanmışsa, istek şu şekilde yapılır :

http://<host&gt;:<port>/<context-path>/login.action

Aynı Servlet sınıflarında olduğu gibi Action sınıflarında da bir mapping uzantısı kullanılabilir.

web.xml dosyasında Servlet mapping aşağıdaki şekilde yapılıyordu :

[codesyntax lang=”xml” lines=”no”]

<servlet>
	<servlet-name>LoginServlet</servlet-name>
	<servlet-class>servlets.LoginServlet</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>LoginServlet</servlet-name>
	<url-pattern>/login</url-pattern>
</servlet-mapping>

[/codesyntax]

http://<host&gt;:<port>/<context-path>/login diyerek LoginServlet isimli sınıfın çağrılması sağlanıyordu.

Action sınıfları için bu sefer struts.xml dosyasında aşağıdaki şekilde bir sabit tanımlanır.

[codesyntax lang=”xml” lines=”no”]

<struts>

  <constant name="struts.action.extension" value="aspx"/> 

  <package name="login" extends="struts-default">
	<action name="login">
		<result>pages/login.jsp</result>
	</action>
  </package>

</struts>

[/codesyntax]

 http://<host>:<port>/<context-path>/login.aspx

Yukarıdaki mapping’de istek tarayıcının adres satırından bir aspx sayfasına yapılıyormuş gibi gözükse de aslında login.jsp sayfası çağrılacaktır. Eğer uzantı hiç istenmiyorsa aşağıdaki tanım yeterli olacaktır.

[codesyntax lang=”xml” lines=”no”]

<struts>

  <constant name="struts.action.extension" value=""/> 

  <package name="login" extends="struts-default">
	<action name="login">
		<result>pages/login.jsp</result>
	</action>
  </package>

</struts>

[/codesyntax]

Bu şekilde bir tanım yapıldığında istek URL’si aşağıdaki gibi olmalıdır.

http://<host&gt;:<port>/<context-path>/login

serialVersionUID Nedir?

Java kodunuzu yazarken Serializable arayüzünü gerçekleştiren sınıflarınızda derleyicinin uyarı verdiğini görürsünüz. Uyarıyı gidermek istediğinizde de IDE’niz sınıf içerisinde serialVersionUID isminde long tipinde bir değişken yaratır.

Bu değişkeni programımız içerisinde hiçbir zaman kullanmasak da JVM için gereklidir.

Özellikle Java EE uygulamalarında sıkça karşılaştığımız bu değişken sayesinde JVM sınıfımızı daha hızlı bir şekilde byte dizisi haline getirir. Yani daha hızlı Serialize eder.

Serialization yapılan, yapılacak her yerde bu değişken yaratılmalıdır.

Java Message Service – JMS

Her mesajlaşma uygulaması için konfigure edilen iki tip yönetim objesi vardır.
  1. Destinations
  2. Connection Factories
Destinations denilen yapılar mesajları almak, tutmak ve yönlendirmek için kullanılırlar. Queue ve Topic Destination’lar olmak üzere ikiye ayrılırlar.
  1. Queue Destination : Point-to-Point mesajlaşma protokolü
  2. Topic Destination : Yayınla-al mesajlaşma protokolü

İstemci Queue’ya erişebilecek bir Connection sınıfı üzerinden bu Queue’ya erişebilir. Yani direk erişemez. Queue’ya erişmek için bu Connection sınıfını kullanıp session oluşturulur. Session üzerinden Queue’ya bağlanılır. Bu bağlantı sınıfına “connection factory” denir. Connection Factory uygulama sunucusu üzerinde tanımlanır.

İstemci tarafı Queue’ya erişebilsin diye Connection Factory oluşturulur.

Connection factory’ler JMS API Client tarafından JMS API Destination’a bağlanmak için kullanılır. İki kategoriye ayrılırlar.

  1. Queue Connection Factories
  2. Topic Connection Factories

 

İstemcilerin Mesaj Göndermesi :

İstemcileri mesaj gönderen uygulamalar olarak düşünebilirsiniz. Gönderilen mesajlar senkron ya da asenkon olabilir. Yani mesaj gönderildikten sonra cevabın ne zaman döneceği belli olmayabilir. Senkron mesajlarda gönderilen mesajın cevabı beklenir.
1

Mesajlar :

Uygulamaya ait bilgileri sarmalamaya yarayan objelerdir. Mesajın 3 parçası vardır.
  1. Header : Mesajı tanımlamak ve yönlendirmek için bilgi barındırır.
  2. Properties : Mesajları sınıflandırmak için kullanılır. Isim/değer tutulur. Mesajlar özelliklerine göre filtrelenebilir.
  3. Body : Mesajın içeriği bulunur.
5 adet mesaj tipi vardır. Sunucudaki queue ya da topic yapılarına bu beş tipte mesajdan ihtiyaca göre bir tanesi gönderilebilir.
2

 

 

Point-to-point Mesajlaşma (Queue) :

Bir mesaj kuyruğu (queue), mesajların tamamı tükenene kadar saklar. Queue ve topic arasındaki en büyük fark, Queue yapısında tek bir mesaj kullanıcısının olmasıdır. Mesajı gönderen ve alan arasında zaman anlamında bir bağımlılık yoktur. Queue’ya gönderilen tüm mesajlar alıcının yaratılmasından önce bile gönderilmiş olsalar sonradan alınabilirler.
Bir tüketici kuyruktan bir mesajı aldıktan sonra aynı mesaj başka birisi tarafından kullanılamaz.
3

Publish/Subscribe Mesajlaşma (Topic) :

Bir Topic’in birden fazla kullanıcısı olabilir. Mesajı üreten istemci mesajları Topic’e gönderir. Topic mesajların tamamı kullanıcılara dağıtılana kadar hepsini saklar. Burada iki taraf arasında zaman bağımlılığı vardır. Mesaj alacak kişiler, Topic’e kayıt olmadan ya da inaktif durumdayken mesaj alamazlar.
4
EJB bileşenleri (entity, session, message-driven beans) ile mesaj göndermek mümkün olabilir. Yalnız JMS API’nin ihtiyaç duyduğu metotların yazılması gerekir.
Senkron mesaj kullanıcıları sunucuyu bloke edip bağladıkları için session, entity ve message-driven bean’ler ile senkron mesaj göndermek sakıncalıdır.
Message-driven bean’ler MessageListener interface’ini implement ederler. Yani asenkron mesajlaşma için kullanılırlar. MessageListener arayüzünde tanımı yapılmış onMessage() metodunu override ederler. Container’a MessageListener kullanıldığının bir şekilde söylenmesi gerekiyor. Bunu da message-driven bean’lerin başında @MessageDriven annotation‘ı ile ifade ediyoruz.
MDB’lerin local ya da remote interface’leri olmaz. MDB’ler Java EE bileşenleri ile direk olarak haberleşmezler. Önce mesajı queue ya da topic yapısına gönderirler. Container’lar mesajları göndermek için havuz kullanabilirler ki çoğu zaman kullanırlar.
Container MDB instance’ı yaratırken newInstance() adındaki metodu otomatik olarak çağırır. Instance yaratıldıkdan sonra çalışacak olan metot PostConstruct metodudur. (Bu metotları annotationlarla belirliyorduk.) Daha sonra Container beani havuza ekler. Bean daha sonra listener metodunun çağrılmasını bekler. Mesaj eklendikçe listener metodu çalışır.
  • MDB’ler public tanımlanır ve aynı diğer beanler gibi final ya da abstract olmaz.
  • Class tanımının başında @MessageDriven annotation’ı olur.
  • mappedName özelliği ile MDB uygulama sunucusunda tanımlanmış olan destination’lara JNDI ismiyle bağlanır.
  • finallize() metotları olmaz.
  • Bean içerisinde event handler metotları tanımlanabilir. Eskiden bu metotları override etmek zorunluydu şimdi bean instance’ı yaratılmadan önce ve sonra eventler oluşuyor. İstersek PostConstruct ve PreDestroy metotlarını yazabiliyoruz. Aynı diğer bean sınıflarındaki gibi herhangi bir isimde void bir metot tanımlanıyor. Bu metot parametre almıyor. Herhangi bir modifier alabiliyor ama uygulamaya özel exception fırlatmaması gerekiyor. Runtime exception’lar önemli değil. Tanımlarının başına da @PostConstruct ya da @PreDestroy yazıyoruz.
EJB’ler arasındaki haberleşmenin senkron olması gerekli değilse yani cevabını hemen beklemiyorsak asenkron haberleşmeyi kullanıyoruz.  Ne zaman okunacağı bizim için önemli olmadığında MDB kullanıyoruz. Mesajlarımızı bırakıyoruz bir ara okunuyor.

PrimeFaces 4.0

Geçtiğimiz günlerde yeni gelecek özelliklerle 3.5 versiyonunun çıkarılacağını duyuran Prime Teknoloji, yeni eklenecek özelliklerin fazlalığından dolayı 3.5 projesini iptal ederek 4.0 versiyonunu çıkaracağını duyurdu.

 

2013 yılının başında piyasaya sürülecek olan yeni versiyonu sabırsızlıkla bekliyorum.

 

ASP.NET için PrimeFaces’i de bir yandan geliştiren grup bu tarafı şimdilik askıya alarak yeni versiyona odaklandığını açıkladı.

4.0 ile birlikte mobil sürümü olan 1.0 versiyonunun da aynı tarihlerde piyasada olacağı tahmin ediliyor.

 

Son sürümü aşağıdaki adresten indirebilirsiniz.

[box type=”download”] PrimeFaces 3.4.1[/box]

 

 

PrimeFaces 3.4 RC1 piyasada

Prime Technology tarafından geliştirilen PrimeFaces framwork’ünün son sürümü görücüye çıktı.

130’dan fazla dosya güncellemesi, Atmosphere Framework ile AJAX Push entegrasyonu ve yeni bileşenleri ile piyasaya sürülen PrimeFaces 3.4 RC1’i aşağıdaki bağlantıdan indirebilirsiniz.

[box type=”download”] PrimeFaces 3.4 RC1 Indir[/box]

Yapılan değişiklikler ile ilgili detaylı bilgi için ise aşağıdaki bağlantıyı kullanabilirsiniz.

[box type=”info”] PrimeFaces 3.4 Yenilikler[/box]

JSP Sayfasında AJAX Kullanımı

Öncelikle AJAX’ın bir programlama dili değil bir kısaltma olduğunu belirtmek isterim. Özellikle öğrencilerimden “Hocam AJAX ile uygulama yazdım, şöle şöle sıkıntı yaşıyorum” gibi geri dönüşler alıyorum. AJAX ile kod yazılmaz, uygulamamızda AJAX kullanabiliriz.

AJAX, “Asynchronous JavaScript and XML” kelimelerinin baş harflerinden oluşur. Yani bir programlama dili değil, var olan birden fazla teknolojinin birlikte kullanılmasına verilen genel bir isimdir. Genellikle dinamik bir web sayfasındaki bilgileri güncellerken sayfanın tamamının yenilenmesi yerine sadece belirli bir kısmının güncellenmesi için kullanılır.

Ajax kullanabilmek için HTML ya da XHTML ve JavaScript / DOM bilmek gerekir. Bunun yanına biraz da CSS bilgisi eklerseniz çok etkin web sayfaları tasarlayabilirsiniz.

[box type=”info”] Günümüzde altyapı olarak AJAX kullanan birçok framework vardır. Örneğin yukarıda bahsettiğim teknolojilerin hiçbirini bilmeden JSF kullanarak AJAX altyapısı ile sayfalarınızı geliştirebilirsiniz.[/box]

AJAX, Google’ın arama sonuçlarını önermeye başlaması ile ünlü oldu diyebiliriz. En başta Google olmak üzere (Maps, Gmail vs.), Youtube, Facebook, Yahoo gibi firmalar AJAX’ın gücünü görerek bu teknolojiyi neredeyse her yerde kullanmaya başlamışlardır.

Gmail ya da Yahoo hesabınızla giriş yaptığınızı düşünün. O sırada yeni bir mail aldığınızda sayfanızın sadece gelen kutusu güncellenecek, kalan kısmı olduğu gibi kalacaktır. Facebook’ta arkadaşlarınızla konuşurken, mesaj atarken ya da bir içerik paylaşırken de aynı şey söz konusu olacaktır.

Kısaca güzeldir, kullanılmalıdır.

Peki hiç bilmeyen birisi AJAX’ı JSP sayfasında nasıl kullanacak? Bu yazımda en basit haliyle kullanımını göstereceğim.

AJAX’ın temel taşı XMLHttpRequest nesnesidir. Bu nesnenin günümüzde bütün tarayıcılar tarafından desteklendiğini söyleyebiliriz. Sadece Internet Explorer 5 ve 6 versiyonlarında desteklenmemiş onun yerine ActiveXObject nesnesi kullanılmıştır. Fakat Microsoft hatasını geç de olsa anlayarak XMLHttpRequest nesnesi kullanmaya başlamıştır.

XMLHttpRequest nesnesi arka planda sunucudaki kodla (Servlet sınıflarını düşünebilirsiniz) iletişime geçerek istemci tarafındaki bilgilerin güncellenmesini sağlar. Bunu yaparken de web sayfasının sadece belirli bir kısmınının içeriğinin değişmesine olanak sağlar.

Tarayıcının XMLHttpRequest nesnesini destekleyip desteklemediğini anlamak için aşağıdaki gibi bir kod yazabiliriz.

[codesyntax lang=”javascript” lines=”no”]

var xmlhttp;    
if (window.XMLHttpRequest) {   // code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
} else {   // code for IE6, IE5
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}

[/codesyntax]

Sunucuya istek gönderebilmek için XMLHttpRequest nesnesinin open() ve send() isimli iki metodu kullanılır.

open() metodu 3 tane parametre alır. İsteği gönderdiğimiz HTTP metodu, isteği gönderdiğimiz sayfa ya da sınıf ve isteğin asenkron ya da senkron gönderildiğini belirten boolean bir değer.

send() metodu ise isteği göndermek için kullanılır. HTTP metodu olarak POST kullanıldığında ise – metoda parametre olarak – sunucuya gönderilecek değerler verilir.

[box type=”info”] HTTP metodu olarak hangi yöntemin kullanılacağına kendiniz karar vermelisiniz. Aralarındaki fark “GET – POST İstekleri” adlı makalemde ele alınmıştır.[/box]

AJAX’ta GET metodu ile istek göndermek için ;

[codesyntax lang=”javascript” lines=”no”]

xmlhttp.open("GET","servletIsmi",true);
xmlhttp.send();

[/codesyntax]

POST metodu ile istek göndermek için ise ;

[codesyntax lang=”javascript” lines=”no”]

xmlhttp.open("POST","servletIsmi",true);
xmlhttp.send();

[/codesyntax]

kullanılır. Sunucuya parametre göndermek için GET metodunda ;

[codesyntax lang=”javascript” lines=”no”]

xmlhttp.open("GET","servletIsmi?isim=Erkin",true);
xmlhttp.send();

[/codesyntax]

ve POST metodunda,

[codesyntax lang=”javascript” lines=”no”]

xmlhttp.open("POST","servletIsmi",true);
xmlhttp.send("isim=Erkin");

[/codesyntax]

kullanılır.

İsteği yukarıdaki gibi gönderdiğimizde bazen tarayımız parametreleri cashlediği için aynı sonucu alırız. Bunun için isteğin her seferinde farklı bir parametre değeri ile gönderilmesi gerekir. En sağlam rasgele değer üretme yöntemi, o anın tarih saat bilgisini rasgele üretilmiş bir ondalikli sayıyla çarpmaktır. Dolayısıyla parametre gönderirken kodu aşağıdaki gibi yazabilirsiniz.

[codesyntax lang=”javascript” lines=”no”]

xmlhttp.open("GET"," servletIsmi?t=" + (new Date().getTime() * Math.random()),true);
xmlhttp.send();

[/codesyntax]

Gönderilen parametrenin sunucuda ille de kullanılması gerekmez. Biz yukarıdaki kod ile her seferinde farklı bir değer gönderdiğimiz için tarayıcının çerez saklama işinden kurtulmuş oluruz.

open() metodundaki son parametre, isteğin senkron ya da asenkron gönderilmesi ise tamamen yazılımcının insiyatifindedir. Senkron gönderilen isteklerde sunucudan cevap dönmesi beklenir. Ancak genellikle sunucuda veri tabanına bağlanarak dönen değerleri sayfada göstermek gibi zaman alan işler yapılır. Bu yüzden son parametre genellikle true verilir ki JSP sayfamızdaki JavaScript kodu sunucu işini yaparken çalışmaya devam etsin.

Peki sayfamızdaki kod çalışırken sunucudan cevap döndüğünü nasıl anlayacağız? Bunun için onreadystatechange adında bir event vardır. Hazır olma durumu her değiştiğinde bu event tetiklenir. Toplamda 5 farklı durumu vardır.

0: istek yaratılmadı
1: sunucu bağlantısı kuruldu
2: istek alındı
3: istek işletiliyor
4: istek işi bitti ve cevap hazır halde

Cevabın geldiğini bu durumları kontrol ederek anlayabiliriz. Örneğin,

[codesyntax lang=”javascript” lines=”no”]

xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
            document.getElementById("bilesenId").innerHTML=xmlhttp.responseText;
        }
}

[/codesyntax]

Yukarıdaki kodda readyState 4 ise yani cevap hazır ise ve status 200 ise yani sayfa bulunmuş ve bir sıkıntı yoksa sayfamızdaki bilesenId id’li bileşen değerini sunucudan gelen değerle güncelle demiş olduk.

[box type=”info”] status sadece 200 ve 404 değerlerini alır. 200 bir sıkıntı olmadığını, 404 ise sayfanın bulunamadığını belirtir.[/box]

Şimdi basit bir uygulama yazalım. JSP sayfamızda bir tane buton olsun. Tıkladığımızda sayfanın tamamı yenilenmeden alt kısıma sunucudan aldığımız text içeriği yazdıralım.

JSP Sayfası :

[codesyntax lang=”asp” lines=”no”]

<%@ page language="java" contentType="text/html; charset=ISO-8859-9" pageEncoding="ISO-8859-9"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript">
    function ajaxMetodu() {
        var xmlhttp;
        if (window.XMLHttpRequest) {    // IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp = new XMLHttpRequest();
         } else {    // IE6, IE5
             xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
         }
         xmlhttp.onreadystatechange = function() {
             if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                 document.getElementById("bilesenId").innerHTML = xmlhttp.responseText;
             }
         }
         xmlhttp.open("GET","sunucudakiSinif",true);
         xmlhttp.send();
     }
 </script>
 </head>
 <body>
     <input type="button" value="AJAX ile bilgi getir" onclick="ajaxMetodu()"/>
     <div id="bilesenId"></div>
 </body>
 </html>

[/codesyntax]

Servlet :

[codesyntax lang=”java” lines=”no”]

package servlets;

import java.io.IOException;
import java.io.PrintWriter;

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

@WebServlet("/sunucudakiSinif")

public class AjaxDeneme extends HttpServlet {

    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("Sunucudan gelen icerik !!!");
    }
}

[/codesyntax]

Dikkat ederseniz butona tıkladığımızda istek sunucudan dönecek ve tarayıcı sayfanın tamamını yenilemeyecektir. Sayfanın görüntüsü de aşağıdaki gibi olacaktır.

AJAX kullandığımızda sunucudan dönen verilerin tipi text tabanlıdır. Yani veriler String ya da XML olarak gelir. Fakat kullanılan Jackson, Google GSon, JSON.simple gibi 3. parti AJAX kütüphaneleri sayesinde nesneleri de web sayfalarımızda rahatça kullanabilmekteyiz.