• Anasayfa
  • Eğitimler
    • JavaScript Eğitimi
    • Angular 2 Eğitimi
    • React.js Eğitimi
    • Java 8 Eğitimi
    • Java EE 7 Eğitimi
    • Spring Framework Eğitimi
    • Git Eğitimi
  • Online Eğitimler
    • Online React.js Eğitimi
    • Online Angular 2 Eğitimi
    • Online Spring Boot Eğitimi
  • Referanslar
  • Hakkında
  • İletişim
KodEdu
  • Anasayfa
  • Eğitimler
    • JavaScript Eğitimi
    • Angular 2 Eğitimi
    • React.js Eğitimi
    • Java 8 Eğitimi
    • Java EE 7 Eğitimi
    • Spring Framework Eğitimi
    • Git Eğitimi
  • Online Eğitimler
    • Online React.js Eğitimi
    • Online Angular 2 Eğitimi
    • Online Spring Boot Eğitimi
  • Referanslar
  • Hakkında
  • İletişim

Jax-RS 2 ve LongPolling destekli Chat uygulaması

  • Posted by Kodedu
  • Categories backend, Genel, Tutorial, Uncategorized, Yazılar, Yazılım
  • Date 16 Nisan 2013

LongPolling; Reverse  Ajax, Comet gibi isimlerle de bilinen, Javascript destekli Web tarayıcılarda sorunsuz bir biçimde çalışabilen bir Push yöntemidir.

HTML 5 ile birlikte, SSE ve Websocket gibi ileri Push teknikleri hali hazırda bulunsada, gerek teknolojilerin halen geliştirilme sürecinde oluşu, gerek se Web tarayıcıların tam olarak desteklemeyişi, LongPolling ve benzeri teknikleri hüküm sahibi kılıyor.

LongPolling tekniğinde, web tarayıcı sunucuya bir istekte bulunur, ve bu istek sunucuda hazır bir yanıt bulunana kadar sunucu üzerinde askıda kalır. Askıda kalan HTTP isteği, bir yanıta (resource) sahip olduğundaysa, mevcut kaynak web tarayıcıya geri gönderilir. Web tarayıcı HTTP kaynağını elde eder etmez yeni bir yoklama (polling) mesajı ileterek, süreç yeni bir HTTP kaynağı hazır olana kadar kendisini tekrarlar.

LongPolling

Zaman zaman, sunucu, web tarayıcı veya mevcut ağ ortamında kaynaklı olarak, askıda kalan yoklama isteğinin başarısız olması da söz konusu olabilir. Bu durumda, web tarayıcı hata bilgisini sunucudan alır almaz, yeniden bir istek göndererek, yoklama tekrardan başlar.

LongPolling tekniğinde, web tarayıcı tarafında, bir Javascript nesnesi olan XMLHTTPRequest nesnesi kullanılabilir. Sunucu tarafındaysa, Jax-RS 2 ile birlikte gelecek olan AsyncronousResponse nesneleri esneklik ve kolaylık açısından kullanılabilir.

Şimdi LongPolling tekniği ve Jax-RS 2 birlikteliğini içeren bir Chat uygulaması örneğini sizlerle paylaşmak istiyorum.

Bağımlı olunan kütüphane

Chat uygulaması bir Servlet konteyner üzerinde kolaylıkla çalışabilir, fakat mevcut konteyner ortamının Servlet 3 standardına uyması gerekmektedir. Çünkü Jax-RS 2, konteyner üzerinde Servlet 3 ile birlikte gelen Asenkron işleyicilerini kullanmaktadır.

<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>

Not:

  • Jax-RS standardının referans uygulayıcı kütüphanesi Jersey’ dir. http://jersey.java.net/
  • Servlet 3 desteği için Jetty 9 veya Tomcat 7 kullanılabilmektedir.

Chat uygulamasının giriş noktası (Rest Endpoint)

@ApplicationPath("app")
public class App extends Application {

@Override
public Set<Class<?>> getClasses() {

Set<Class<?>> sets=new HashSet<>();
sets.add(Chat.class);
return sets;

}
}

Yukarıda @ApplicationPath notasyonuyla sarmalanan Application sınıfı türünden nesne, Chat uygulamasının giriş noktasıyın içermektedir. Bir HashSet içine tanımlanan Chat sınıfı ise, Chat uygulamasına ait bir Rest kaynağı olarak tanımlanmaktadır.

Chat sınıfı (Chat Resource)

@Path("/chat")
public class Chat {

final static Map<String, AsyncResponse> beklemeKuyrugu = new ConcurrentHashMap<>();
final static ExecutorService ex = Executors.newSingleThreadExecutor();

@Path("/{nick}")
@GET
@Produces("text/plain")
public void askidaKal(@Suspended AsyncResponse asyncResp, @PathParam("nick") String nick) {

beklemeKuyrugu.put(nick, asyncResp);

}

@Path("/{nick}")
@POST
@Produces("text/plain")
@Consumes("text/plain")
public String mesajGonder(final @PathParam("nick") String nick, final String mesaj) {

ex.submit(new Runnable() {

@Override
public void run() {

Set<String> nicks = beklemeKuyrugu.keySet();
for (String n : nicks) {

// Mesaj gondericisinden haric herkese gonderilir.
if (!n.equalsIgnoreCase(nick))
beklemeKuyrugu.get(n).resume(nick + " dedi ki: " + mesaj);

}
}
});

return "Mesaj gönderildi..";

}
}

HTTP/GET metoduyla  erişilen askidaKal(..) metodu LongPolling işlemini gören bir RESTful metodudur. Bu metod üzerinde parametre olarak bulunan AsyncResponse türünden parametre, sunucu üzerinde askıda tutulacak LongPolling yanıt nesnesini tanımlamaktadır. AsyncResponse türünden nesneler, Jax-RS ortamından otomatik olarak sağlanırken, duraklatılan (suspended) bu nesneler, geliştirilen mimari çerçevesinde istenildiği zaman yanıt olarak kullanıcıya (web tarayıcıya) sunulabilirler. askidaKal(..) metodunda bulunan ikinci parametre [ @PathParam(“nick“) String nick  ] ise, metoda URL üzerinde gönderilen kullanıcı Nick adını elde etmektedir.

Askıda tutulan AsyncResponse nesnelerinin hangi kullanıcıya ait olduğuna sonradan ihtiyaç duyulmaktadır. Bu maksatla, bir Concurrent Map yapısı olan, ConcurrentHashMap bu iş için kullanılabilir. Bu sayede askidaKal(..) metoduna gönderilen her bir nick -> AsyncResponse nesnesi kayıt altında tutulmuş olur.

Chat sınıfının ikinci metodu olan mesajGonder(..) HTTP /POST metoduyla erişilebilen ve Chat mesajlarını web tarayıcıdan elde eden RESTful yordamı olarak iş görmektedir.

Kullanıcılar bir Chat mesajını Nick isim bilgisiyle birlikte  sunucuya gönderdiklerinde, mesajGonder(..) RESTful metodu bu bilgileri, metod parametrelerinde elde eder, ve bu bilgiler ExecutorService nesnesi üzerinden Asenkron olarak işletilirler. Burada kullanılan ExecutorService nesnesi yerine elbette basit bir Thread de kullanılabilir.

new Thread(new Runnable(){    …   }).start(); gibi. Burada temel mesele, gönderilen mesajın arkaplanda koşulması ve mevcut /POST isteğinin sekteye uğratılmaması, daha doğrusu, mevcut /POST isteğinin tüm kullanıcılara Push edilen mesaj bilgilerinin beklemesini engellemektir.

mesajGonder(..) yordamı içindeki Runnable görev nesnesi içinde, ConcurrentHashMap nesnesi içine  bir evvelki askidaKal(..) yordamında doldurulan nick -> AsyncResponse çifti tüketilir, ve kullanıcının kendisi hariç, askıda tutulan tüm AsyncResponse nesnelerine bu Chat mesajı iletilir. AsyncResponse nesnelerinin içinde bulunan resume() metodu, askıda tutulan (@Suspended) yanıt nesnesini, yanıtlamaya olanak tanır. Yani önce duraklat (suspend) ve Chat mesaj kaynağı hazır olduğunda devam ettir (resume) gibi.

Html bileşenleri

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<span></span>
<table>
<tr>
<td>Nick:</td>
<td><input id="nick"/></td>
</tr>
<tr>
<td>Mesaj:</td>
<td><textarea id="mesaj" disabled="disabled"></textarea></td>
</tr>
</table>

<button>Gönder</button>

<ul></ul>

<script src="resources/jquery-1.9.1.js" type="text/javascript"></script>
<script type="text/javascript" src="resources/chat.js"></script>

</body>
</html>

Yukarıdaki Html sayfasında, bir Html table nesnesi içine dizelenmiş bir Nick girdi alanı, mesajın girileceği textarea alanı ve mesajın gönderileceği bir Html butonu yer almaktadır. Uygulama ilk açıldığında kullanıcıdan Nick adının girilmesi beklendiği için, textarea alanı başlangıçta veri girilemez (disabled) yapılmıştır. Kullanıcı ilk isteği (Nick adını) gönderdiğinde, bu alan değiştirilemez olmaktan çıkartılarak mesaj yazılabilir hale getirilir. Ayrıca, Nick adı sunucuya gönderildiğinde (yani ilk yoklama isteği yapıldığında)   class tipi nick olan ( <tr> )  Html tablo satırı elemanı gizlenir.

Chat uygulamasının XMLHTTPRequest nesneleriyle, HTTP isteklerini asenkron olarak sağlaması gerekmektedir. Biz bu uygulamada bu işlemleri kolaylaştıran ve arka planda XMLHTTPRequest nesnelerini kullanan Jquery Ajax kütüphanesinden faydalanacağız. Jquery bağımlılığına ek olarak, proje içinde bir de, kendi yazdığımız chat.js betiği bulunmaktadır.

chat.js

// Yoklama fonksiyonu bir kereliğine çağrılmalı,
// Hata veya başarım durumunda kendisini özyinelemeli olarak çağıracaktır.
var yokla = function () {

$.ajax({
type: "GET", // HTTP Get isteği
url: "/app/chat/" + $("#nick").val(),  // askidaKal(..) metoduna erişir
dataType: "text", // Gelecek veri tipi text
success: function (mesaj) {

// Mesaj alındığında, <li/> elemanına mesaj eklenir.
$("ul").append("<li>" + mesaj + "</li>");

yokla(); // Bir mesaj tüketildiğinde tekrar yoklamaya bağla.
},

error: function () {

yokla(); // Bir hata olursa tekrar yoklamaya başla.

}

});
}

// Gönder butonuna tıklandığında; 
$("button").click(function () {

if ($(".nick").css("visibility") === "visible") {  // <tr> satırı görünür ise;
$("textarea").prop("disabled", false); // veri girilebilir yap
$(".nick").css("visibility", "hidden"); // <tr> satırı görünmez yap;
$("span").html("Chat başladı.."); // Bilgi mesajı

// Yoklama işlemi bir sefer başlatılmalı
yokla();

}

else // ilk sefer değilse ;
$.ajax({

type: "POST", // HTTP POST isteği
url: "/app/chat/" + $("#nick").val(), // mesajGonder(..) metoduna erişir.
dataType: "text", // Gelecek veri tipi text
data: $("textarea").val(), // Gönderilecek Chat mesajı
contentType: "text/plain", // Gönderilen Chat mesajının türü
success: function (data) {

$("span").html(data); // Başarılıysa [Mesaj gönderildi..] yazar.

// Blink efekt
$("span").fadeOut('fast', function () {
$(this).fadeIn('fast');

});
}
});
});

Uygulamanın test edilmesi

Uygulamanın pom.xml yapılandırma dosyasında Jetty 9.0.0.RC2 eklentisi yer aldığından, uygulama rahatlıkla ;

> mvn jetty:run-war

komutuyla çalıştırılabilir. Uygulamaya http://localhost:8080/ adresinden erişilebilir.

Ben henüz Maven bilmiyorum diyorsanız Altuğ Bilgin Altıntaş hocamızın aşağıdaki videolarını izleyebilirsiniz.

  • https://www.kodedu.com/2011/03/apache-maven-teknolojisine-giris-video/
  • https://www.kodedu.com/2011/03/apache-maven-ile-basit-bir-web-uygulamasi-apache-wicket/

Uygulama kodlarına https://github.com/rahmanusta/JaxRS-LongPolling/ üzerinden

Uygulamanın çalışır haline ise http://discoverjavaee.com/JaxRS-LongPolling/ üzerinden erişebilirsiniz.

 

Tekrar görüşmek dileğiyle..

Tag:jax-rs 2, longpolling

  • Share:
author avatar
Kodedu

Previous post

Java API for JSON Processing – JSON nesneleri okumak ve yazmak
16 Nisan 2013

Next post

Backbone.js Webineri Ardından
29 Nisan 2013

You may also like

api-logo
Swagger Nedir? Neden kullanılır?
10 Ekim, 2018
spring-cli-logo
Spring CLI ile Spring Boot Projeleri Hazırlamak
21 Ağustos, 2017
eureka_architecture
Spring Cloud Netflix ve Eureka Service Discovery
3 Temmuz, 2017

    2 Comments

Leave A Reply Cevabı iptal et

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta listesine kayıt olun!






Gözde yazılar

Sürekli Entegrasyon Yaklaşımları – (ücretsiz webiner)
16Tem2012
Java API for JSON Processing – Creating JSON Objects
15Haz2013
EclipseLink JPA : L2 Cache Stratejileri
10Eki2012
Cloud Jenkins (BuildHive)
18May2012

Son Yazılar

  • Java’da Record’lar 27 Ocak 2020
  • Swagger Nedir? Neden kullanılır? 10 Ekim 2018
  • Spring CLI ile Spring Boot Projeleri Hazırlamak 21 Ağustos 2017
  • Spring Cloud Netflix ve Eureka Service Discovery 3 Temmuz 2017
  • Online React.js Eğitimi ardından (15-25 Mayıs 2017) 31 Mayıs 2017

Son Yorumlar

  • Coupling ve Cohesion Kavramları Nedir? için Hilal
  • Naïve Bayes Sınıflandırma Algoritması için Rahman Usta
  • Naïve Bayes Sınıflandırma Algoritması için Mete
  • YAML Nedir? Neden YAML Kullanmalıyız? için kara
  • JWT (JSON Web Tokens) Nedir? Ne işe yarar? için Furkan

Get Java Software

Arşivler

Bizi takip edin

React.js Eğitimi Başlıyor
11-22 Eylül, 2017
Eğitmen
Rahman Usta
İletişim

merhaba@kodedu.com

  • Hakkında
  • Gizlilik Politikası
  • İletişim
  • Referanslar
Kodedu Bilişim Danışmanlık
Cemil Meriç mah. Çelebi sok.
No:16/3 Ümraniye/İSTANBUL
Tel: 0850 885 38 65
Alemdağ V.D.: 8960484815

KODEDU © Tüm hakları saklıdır.