31 Temmuz 2010 Cumartesi

JMS Point to Point Messaging

Uygulamalar arası mesajlaşma nasıl yapılmaktadır? Uygulamalardan biri Gönderen Uygulama, diğeri ise Alan Uygulamadır. Gönderen uygulama mesajı kuyruğa yollar, alan uygulama ya kuyruğu dinler ya da direk kuyruktan alır. Bir gönderen, iki alan uygulama örnegini aşağıda inceleyeceğiz.

• Queue Sender
• Synchronous Queue Receiver
• Asynchronous Queue Receiver

Gönderen Uygulama
1. InitialContext nesnesi tanımlanır.
2. Tanımlanan Context nesnesi JMS Server’da tanımlanmış olan kuyruk(queue) yapısını arar.
3. Tanımlanan kuyruk yapısı için QueueConnectionFactory nesnesi tanımlanır.
4. QueueConnectionFactory nesnesini kullanarak QueueConnection nesnesini yaratırız.
5. Yaratılan Connection uzerinden QueueSession nesnesini yaratırız. Bu session’ın transacted olup olmamasına burda karar veririz.
6. QueueSession nesnesini kullanarak QueueSender nesnesini yaratırız ve ilgili mesajımızı tanımlarız.
7. Tanımladığımız mesajı gönderici kuyruk yapısı ile göndeririz.
Yukarıda yapılan anlatımları kodlamak istersek :

QueueConnection queueConn = null;
try {
InitialContext ctx = new InitialContext();
Queue queue = (Queue) ctx.lookup("queue/queue0");
QueueConnectionFactory connFactory = (QueueConnectionFactory) ctx.lookup("queue/connectionFactory");
queueConn = connFactory.createQueueConnection();
QueueSession queueSession = queueConn.createQueueSession(false, Session.DUPS_OK_ACKNOWLEDGE);
QueueSender queueSender = queueSession.createSender(queue);
queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
TextMessage message = queueSession.createTextMessage("Asin Akdeniz");
queueSender.send(message);
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}finally{
if(queueConn != null){
try {
queueConn.close();
} catch (JMSException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
}//end of finally



Alıcı Uygulama
Alıcı uygulamalar senkron ve asenkron alıcılar olabilmektedir. Senkron Alıcı, gönderici gibi ilk tanımlamaları yapar bir kaç detay dışında. Initial Context i kullanarak kuyruk yapısı tanımlanır, connection kurulur, session yaratılır. Farklılık bundan sonra başlıyor, QueueSender yerine mesajların alımının sağlayacak QueueReceiver nesnesi tanımlanır. QueueSender’den sonra yazılacak kod parçası aşağıdaki gibidir.

QueueReceiver queueReceiver = queueSession.createReceiver(queue);
queueConn.start();
TextMessage message = (TextMessage) queueReceiver.receive();
queueConn.close();

Asenkron alıcı uygulaması biraz daha farklılaşmaktadır. Burada alıcı sınıfın mesaj dinleyicileri tanımlanır. Tanımlayacağımız alıcı sınıfın MessageListener Java arayüzünü implement etmesi gerekmektedir. Bu arayüz sadece onMessage metodunu içermektedir. Tanımladığımız istemci nesnesini QueueReceiver’ın setMessageListener metoduna register ederiz.

InitialContext ctx = new InitialContext();
Queue queue = (Queue) ctx.lookup("queue/queue0");
QueueConnectionFactory connFactory = (QueueConnectionFactory) ctx.lookup("queue/connectionFactory");
QueueConnection queueConn = connFactory.createQueueConnection();
QueueSession queueSession = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueReceiver queueReceiver = queueSession.createReceiver(queue);
Main asyncReceiver = new Main();
queueReceiver.setMessageListener(asyncReceiver);
queueConn.setExceptionListener(asyncReceiver);
queueConn.start();
System.out.print("waiting for messages");
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.print(".");
}
System.out.println();
queueConn.close();
}
public void onMessage(Message message){
TextMessage msg = (TextMessage) message;
try {
System.out.println("received: " + msg.getText());
} catch (JMSException ex) {
ex.printStackTrace();
}
}
public void onException(JMSException exception){
System.err.println("an error occurred: " + exception);
}


25 Temmuz 2010 Pazar

Java Message Service (JMS) Giriş

Mesajlaşma Nedir?

Yazılım bileşenleri ya da uygulamaları arasında iletişimi sağlayan metodtur. Istemci (Client) mesajı başka bir istemciye gönderir ya da alır. Gönderenin (Sender), alıcı (receiver) hakkında herhangi birşey bilmesine gerek yok tersi içinde aynısı geçerli. Gönderenin ve alanın sadece mesaj formatı konusunda bilgi sahibi olması gerekmektedir. Bu bağlamda mesajlaşmanın RMI gibi teknolojilerden (uzaktaki uygulamanın metod bilgisinin gerektirtiği) farklı olduğu anlaşılmaktadır.

JMS API?

Java Message Service, okuma/gonderme/alma/yaratma gibi mesajlaşma özelliklerine sahip olan Java API’sidir. JMS uygulama bileşenleri arasında doğrudan iletişim kurmak yerine bir mesaj sunucusu (Message Server) aracılığıyla iletişim kurmasını sağlar. JMS iletişimi Asenkron ve güvenli sağlanır. Istemci mesajı diğer istemciye gonderir ve istemci bu mesajı gerektiği zaman alır. Bu mesajlaşma güvenilir bir şekilde yapılır yani mesajlar kaybolmaz ya da birden fazla kez yollanmaz.

JMS Mimarisi?

Kısaca JMS elemanları hakkında bilgi vermek gerekirse:

· JMS Provider (JMS interfacelerinin implementasyonudur.)

· JMS Client (Mesajı gönderen ya da alan uygulamadır.)

· JMS Producer/Publisher (JMS istemcisinin mesajı yaratması ve göndermesidir.)

· JMS Consumer/Subscriber (JMS istemcisinin mesajı almasıdır.)

· JMS Message (JMS istemcileri arasında transfer edilen veridir.)

· JMS Queue (Yollanan mesajların okunmaya hazır halde beklediği kuyruk veri yapısıdır.)

· JMS Topic (Dağıtıcı istemci tarafından dağıtılan mesajların birden fazla alıcı istemci tarafından alınmasını sağlayan mekanizmadır.)

JMS Model

JMS API si 2 modeli desteklemektedir.

· Point to point or Queuing Model

· Publish and Subscribe Model

Point to point : Gönderici istemci mesajı kuyruk (queue) yapısına yollar, alıcı istemci ise bu kuyruk yapısından mesajı olur. Sadece bir alıcı mesajı okuyabilir ve her okunan mesaj için alındığına dair bilgilendirme yapılır.









Publish/Subscribe Model: belirlenen mesaj başlığına (message topic) mesajları yollar. Birden fazla istemci bu mesaj başlığına register olup gelen mesajları alır. Bu istemcilerin birbirlerinden ya da gondericiden haberi olmaz. İstemciler listener olgusuna kaydolur ve yollanan mesajları alır. Mesaj bütün kayıtlı istemciler tarafından alındıktan sonra silinir.









JMS i kullanmak için öncelikle session ve kuyrukları (queue) yönetecek JMS provider’a ihtiyaç vardır.

· OpenJMS, from The OpenJMS Group

· Open Message Queue, from Sun Microsystems

· JBoss Messaging from JBoss

· Apache ActiveMQ

bunlardan bazıları..

JMS 2 bölümünde kavramlar daha da detaylandırılacak.


22 Temmuz 2010 Perşembe

Java Blob ve SerialBlob

Blob (Binary Large Object), adında da anlaşıldığı gibi veritabanı sütununa büyük binary (ikili) verileri saklama yöntemidir. Farklı veri tabanlarında farklı şekilde ele alınır, fakat ortak karekteristik özelliklerini şöyle sıralayabiliriz.

1. Binary (ikili) verileri saklar.

2. Blob verileri maksimum 4 GB büyüklügündeki verilerdir.

3. Genelde tablo içine direk olarak saklanmaz. Farklı saklama alanına saklanır ve tablo üzerindeki referans adresi ile erişilir.


Diğer büyük veri nesneleri

1. CLOB, büyük karakter nesneleridir.

2. BFILE ,veritabanı dışında saklanan 4 GB tan büyük kütüklere (file) referans gösterir.

Java 1.2 den beri java.sql.Blob interface’i olarak tanımlıdır. Java.sql.ResultSet interface’inden getBlob() metodu ile donen degeri Blob interface’ine atarız ve bu interface metodları üzerinde güncelleme yapabiliriz.

Statement stmt = connection.createStatement();

ResultSet rs = stmt.executeQuery("SELECT * FROM table");

Blob blob = rs.getBlob();

Tersi durumu nasıl ele alabiliriz? Java da Blob nesnesini olusturup, ilgili veriyi atamak ve veritabanına kaydetmek veya ORM yontemi ile eşleştirmek.

Java 1.4 te Blob’u tanımlayamıyoruz, ama java 1.5’e eklenen SerialBlob sınıfı ile bu eksiklik giderilmiş. Java 1.4 te çalışanlar, Java 1.5 te SerialBlob ve SerialException sınıflarını projenize dahil edebilirsiniz. Böylece SerialBlob’u Java 1.4 te Blob interface’ni tanımlamak için kullanabilirsiniz aşağıdaki gibi.

Blob blob = new SerialBlob( byte[] byteArray );

Amacımız olan Blob nesnesini Java 1.4 te bu şekilde tanımlamış oluruz.

16 Temmuz 2010 Cuma

SOAPHeader with Java

WSDL tanımlaması yaparken soap mesajın header’ında gitmesini istedigimiz iletiler için WSDL tanımlamasına soap:header ekleriz .Bu tanımlama tamamen opsiyoneldir. WSDL, SOAP Header tanımlamasını input ve output mesajları için ayrı ayrı yapmamıza imkan vermektedir. Böylece istedigimiz mesajları soap mesajın header’ında istemde mi gönderelim? yoksa sonucta mı alalım? kararını verebiliriz. Header için tanımlanan nesne için ayrı bir wsdl:message tanımlamamız durumunda WSDL den Apache Axis ile kodları oluşturdugumuz durumda maalesef header için tanımladıgımız sınıfları yaratmamaktadır. İlgili header sınıfının Axis tarafından yaratılması için wsdl:input için tanımlanan message ın referans gösterdigi wsdl:message içinde header’ı wsdl:part olarak tanımlamız gerekmektedir. Aşağıdaki gibi tanımlamımızı yaparsak Apache Axis, header tanımlamalarımız için ilgili sınıfları yaratır ve tanımladıgımız metodlara parametre olarak set eder.

<wsdl:message name=" "> //input icin tanımlanan message

<wsdl:part name=" " element=" "/>

<wsdl:part name=" " element=" "/> //Header icin tanımlanan part

<\wsdl:message>

<wsdl:input>

<soap:body use="literal"/>

<soap:header use="literal" part=" " message=" ">soap:header>

<\wsdl:input>

<wsdl:output>

<soap:body use="literal"/>

<soap:header use="literal" part=" " message=" ">soap:header>

<\wsdl:output>

Header için ayrı bir wsdl:message tanımlamamız durumunda Axis, header için tanımlanan ilgili sınıfları yaratmamamaktadır bu da Soap Header mesajlarını işleyememize neden olmaktadır. Yaratılmaması durumunda servis çağrımında ya da sonucunda soap header’ı kodlamamız gerekir. Axis Handler’dan türeyen tanımladığımız sınıf içinde SOAPHeader’ı aşağıdaki gibi kodlarız.

SOAPMessage soapMessage = messageContext.getResponseMessage();

SOAPHeader soapHeader = (SOAPHeader) soapMessage.getSOAPHeader();

SOAPHeaderElement soapHeaderElement = new org.apache.axis.message.SOAPHeaderElement("", "");

SOAPElement transactionIdElement = soapHeaderElement.addChildElement("");

soapHeaderElement.addTextNode();

soapHeader.addChildElement(soapHeaderElement);