10. Dağıtık Uygulamaların Oluşturulması CORBA
10.1. Giriş
Önceki bölümde, RMI paketini kullanarak Java'da dağıtık uygulamaların nasıl oluşturulacağını gördük. Burada aynı konuyu, bu kez CORBA mimarisiyle ele alacağız. CORBA (Common Object Request Broker Architecture), bilgi teknolojisi sektöründeki birçok şirketi bir araya getiren OMG (Object Management Group) tarafından tanımlanan bir spesifikasyondur. CORBA, farklı dillerde yazılmış uygulamaların erişebileceği bir “yazılım veriyolu” tanımlar:

CORBA ile dağıtık bir uygulamanın oluşturulmasının, Java RMI ile kullanılan yönteme yakın olduğunu göreceğiz: kavramlar birbirine benzemektedir. CORBA, diğer dillerde yazılmış uygulamalarla birlikte çalışabilme avantajı sunar.
10.2. Bir CORBA uygulamasının geliştirme süreci
10.2.1. Giriş
Bir CORBA istemci-sunucu uygulaması geliştirmek için aşağıdaki adımları izleyeceğiz:
- IDL (Arayüz Tanımlama Dili) ile sunucu arayüzünün yazılması
- sunucunun "iskelet" ve "stub" sınıflarının oluşturulması
- sunucunun yazılması
- istemcinin yazılması
- tüm sınıfların derlenmesi
- CORBA hizmet dizinini başlatma
- sunucunun başlatılması
- istemcinin başlatılması
İlk örnek olarak, RMI bağlamında daha önce kullanılan yankı sunucusunu ele alacağız. Böylece okuyucu, iki yöntem arasındaki farkları görebilecektir.
Uygulama, jdk1.2 ile test edilmiştir.
10.2.2. Sunucu arayüzünün yazılması
Java RMI’te olduğu gibi, istemci açısından sunucu, arayüzüyle tanımlanır. Sunucuyu uygulayan sınıflar istemci için gerekli olmasa da, arayüzündeki sınıflar gereklidir. Java RMI'te, sunucunun "iskelet" ve "stub" sınıflarını oluşturan bir Java arayüzü kullanılırken, Java CORBA mimarisinde arayüzün Java dışındaki bir dil ile tanımlanması gerekmektedir. Bu arayüz, bazıları istemci tarafından, bazıları ise sunucu tarafından kullanılan birkaç sınıfın oluşturulmasına yol açacaktır.
Yankı arayüzünün tanımı şu şekilde olacaktır:
Arayüz tanımı, echo.idl adlı bir dosyada depolanacaktır. Bu tanım, OMG'in IDL (Arayüz Tanım Dili) dilinde yazılmıştır. Kullanılabilir hale gelmesi için, CORBA uygulamasını geliştirmek için kullanılan dilde kaynak dosyalar oluşturacak bir program tarafından analiz edilmesi gerekir. Burada, önceki arayüzden yola çıkarak uygulama için gerekli olan .java kaynak dosyalarını oluşturacak olan idltojava.exe programını kullanacağız. idltojava.exe programı, JDK ile birlikte sunulmamaktadır. Bu program, Sun’ın http://java.sun.com adresindeki web sitesinden edinilebilir.
Yukarıdaki idl arayüzünün birkaç satırını inceleyelim:
Java’daki echo paketine eşdeğerdir. Arayüzün derlenmesi sonucunda, Java sınıflarını içeren echo c.a.d java paketi oluşturulur.
Java'daki iSrvEcho arayüzüne eşdeğerdir. Bir Java arayüzü oluşturacaktır.
Java'daki String echo(String msg) komutuna eşdeğerdir. IDL dilindeki türler, Java dilindeki türlerle tam olarak eşleşmez. Eşleşmeler bu bölümün ilerleyen kısımlarında verilmiştir. IDL dilinde, bir fonksiyonun parametreleri giriş (in), çıkış (out) veya giriş-çıkış (inout) parametreleri olabilir. Burada, echo yöntemi, bir karakter dizesi olan msg giriş parametresini alır ve sonuç olarak bir karakter dizesi döndürür.
Yukarıdaki arayüz, yankı sunucumuzun arayüzüdür. Hatırlatmak gerekirse, bir uzak arayüz, istemcilerin erişebileceği sunucu nesnesinin yöntemlerini tanımlar. Burada, istemciler için yalnızca echo yöntemi kullanılabilir olacaktır.
10.2.3. Sunucunun IDL arayüzünün derlenmesi
Sunucu arayüzü tanımlandıktan sonra, ilgili Java dosyaları oluşturulur.
E:\data\java\corba\ECHO>dir *.idl
ECHO IDL 78 15/03/99 13:56 ECHO.IDL
E:\data\java\corba\ECHO>d:\javaidl\idltojava.exe -fno-cpp echo.idl
-fno-cpp seçeneği, ön işlemcinin kullanılmayacağını belirtmek için kullanılır (çoğunlukla C/C++ ile kullanılır). echo.idl dosyasının derlenmesi sonucunda, içinde aşağıdaki dosyaların bulunduğu bir echo alt dizini oluşturulur:
E:\data\java\corba\ECHO>dir echo
_ISRVE~1 JAV 1 095 17/03/99 17:19 _iSrvEchoStub.java
ISRVEC~1 JAV 311 17/03/99 17:19 iSrvEcho.java
ISRVEC~2 JAV 825 17/03/99 17:19 iSrvEchoHolder.java
ISRVEC~3 JAV 1 827 17/03/99 17:19 iSrvEchoHelper.java
_ISRVE~2 JAV 1 803 17/03/99 17:19 _iSrvEchoImplBase.java
iSrvEcho.java dosyası, sunucu arayüzünü tanımlayan Java dosyasıdır:
/* * Dosya: ./ECHO/ISRVECHO.JAVA * Kaynak: ECHO.IDL * Tarih: 15 Mart 1999 Pazartesi 13:56:08 * Tarafından: D:\JAVAIDL\IDLTOJ~1.EXE Java IDL 1.2 18 Ağustos 1998 16:25:34 */
package echo;
public interface iSrvEcho
extends org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity {
String echo(String msg)
;
}
Görüldüğü üzere, bu dosya IDL arayüzünün neredeyse kelimesi kelimesine çevirisidir. Diğer .java dosyalarının içeriğine bakmak isterseniz, daha karmaşık şeyler bulacaksınız. İşte bu farklı dosyaların rolüne ilişkin belgelerde yazanlar:
sunucu arayüzü
önceki iSrvEcho arayüzünü uygular. Bu, dağıtılmış uygulama için gerekli CORBA işlevlerini sunucuya sağlayan, sunucunun “iskeleti” niteliğindeki soyut bir sınıftır.
Bu, istemcinin kullanacağı sunucunun görüntüsüdür (“stub”). İstemciye, sunucuya erişmek için gerekli CORBA işlevlerini sağlar.
CORBA nesne referanslarının yönetimi için gerekli yöntemleri sağlar
Arayüz yöntemlerinin giriş-çıkış parametrelerinin yönetimi için gerekli yöntemleri sağlar.
10.2.4. IDL arayüzünden oluşturulan sınıfların derlenmesi
Yukarıdaki sınıfları derlemek iyi bir fikirdir. Başka bir örnekte göreceğimiz üzere, burada idltojava oluşturucusunun hatalı çalışmasından kaynaklanan hataları tespit edebiliriz. Burada her şey yolunda gidiyor ve derleme işleminden sonra echo paket dizininde aşağıdaki dosyalar bulunuyor:
E:\data\java\corba\ECHO\echo>dir
_ISRVE~1 JAV 1 095 17/03/99 17:19 _iSrvEchoStub.java
ISRVEC~1 JAV 311 17/03/99 17:19 iSrvEcho.java
ISRVEC~2 JAV 825 17/03/99 17:19 iSrvEchoHolder.java
ISRVEC~3 JAV 1 827 17/03/99 17:19 iSrvEchoHelper.java
_ISRVE~2 JAV 1 803 17/03/99 17:19 _iSrvEchoImplBase.java
_ISRVE~1 CLA 2 275 18/03/99 11:25 _iSrvEchoImplBase.class
_ISRVE~2 CLA 1 383 18/03/99 11:25 _iSrvEchoStub.class
ISRVEC~1 CLA 251 18/03/99 11:25 iSrvEcho.class
ISRVEC~2 CLA 2 078 18/03/99 11:25 iSrvEchoHelper.class
ISRVEC~3 CLA 858 18/03/99 11:25 iSrvEchoHolder.class
10.2.5. Sunucu Kaydı
10.2.5.1. iSrvEcho arayüzünün uygulanması
Yukarıda iSrvEcho arayüzünü tanımladık. Şimdi bu arayüzü uygulayan sınıfı yazıyoruz. Bu sınıf, yukarıda belirtildiği gibi iSrvEcho arayüzünü zaten uygulayan _iSrvEchoImplbase.java sınıfından türetilecektir.
// ithal edilen paketler
import echo.*;
// uzaktan yankı işlevini uygulayan sınıf
public class srvEcho extends _iSrvEchoImplBase{
// yankı işlevini gerçekleştiren yöntem
public String echo(String msg){
return "[" + msg + "]";
}// yankı sonu
}// sınıf sonu
Kod kendiliğinden anlaşılır. Bu sınıf, iSrvEcho arayüzünün paketinin üst dizininde bulunan srvEcho.java dosyasına kaydedilir.
Doğrulamak için derleme yapabilirsiniz:
E:\data\java\corba\ECHO>j:\jdk12\bin\javac srvEcho.java
E:\data\java\corba\ECHO>dir
ECHO IDL 78 15/03/99 13:56 ECHO.IDL
SRVECH~1 CLA 488 18/03/99 11:30 srvEcho.class
SRVECH~1 JAV 252 15/03/99 14:02 srvEcho.java
ECHO <REP> 17/03/99 17:19 echo
10.2.5.2. Sunucu oluşturma sınıfının yazılması
RMI istemci-sunucu uygulamasında olduğu gibi, bir CORBA sunucusunun da istemciler tarafından erişilebilir olması için bir dizine kaydedilmesi gerekir. Geliştirme aşamasında, bu kayıt prosedürü, uygulamanın CORBA mi yoksa RMI mi olduğuna göre farklılık gösterir. Aşağıda, serveurEcho.java dosyasına kaydedilmiş CORBA yankı sunucusuna ait kayıt yer almaktadır:
// ithal edilen paketler
import echo.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
//----------- serveurEcho sınıfı
public class serveurEcho{
// ------- main: yankı sunucusunu başlatır
// pg sözdizimi machineAnnuaire portAnnuaire nomService
// makine: rehberi destekleyen makine CORBA
// bağlantı noktası: rehberin bağlantı noktası CORBA
// nomService: kaydedilecek hizmet adı
public static void main(String arg[]){
// argümanlar mevcut mu?
if(arg.length!=3){
System.err.println("Syntaxe : pg machineAnnuaire portAnnuaire nomService");
System.exit(1);
}
// argümanları alıyoruz
String machine=arg[0];
String port=arg[1];
String nomService=arg[2];
try{
// Çalışmak için bir CORBA nesnesine ihtiyacımız var
String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
ORB orb=ORB.init(initORB,null);
// hizmeti hizmet dizinine ekliyoruz
// Adı srvEcho olacak
org.omg.CORBA.Object objRef=
orb.resolve_initial_references("NameService");
NamingContext ncRef=NamingContextHelper.narrow(objRef);
NameComponent nc= new NameComponent(nomService,"");
NameComponent path[]={nc};
// sunucuyu oluşturup srvEcho hizmetiyle ilişkilendiriyoruz
srvEcho serveurEcho=new srvEcho();
ncRef.rebind(path,serveurEcho);
orb.connect(serveurEcho);
// takip
System.out.println("Serveur d'écho prêt");
// istemcilerin isteklerini bekleme
java.lang.Object sync=new java.lang.Object();
synchronized(sync){
sync.wait();
}
} catch(Exception e){
// bir hata oluştu
System.err.println("Erreur " + e);
e.printStackTrace(System.err);
}
}// ana
}// serveurEcho
Aşağıda, ilk bakışta karmaşık görünen ayrıntılara girmeden sunucunun başlatılmasının ana hatlarını açıklıyoruz. Önceki örnekten, tüm CORBA sunucularında tekrar karşımıza çıkacak olan ana hatları akılda tutmak gerekir.
10.2.5.2.1. Sunucu ayarları
Bir CORBA sunucusu, belirli bir makine ve bağlantı noktasında çalışan bir dizin hizmetine kaydolmalıdır. Uygulamamız bu iki veriyi parametre olarak alacaktır. Bu şekilde kaydedilen hizmetin bir adı olmalıdır; bu, üçüncü parametre olacaktır.
10.2.5.2.2. CORBA dizin hizmetine erişim nesnesini oluşturma
Dizin hizmetine erişmek ve yankı sunucumuzu kaydetmek için, aşağıdaki sınıf yöntemiyle elde edilen ORB (Object Request Broker) adlı bir nesneye ihtiyacımız var:
Args : tableau de paires de chaînes de caractères, chaque paire étant de la forme (paramètre,valeur)
Prop : propriétés de l’application
Örnekte, ORB nesnesini elde etmek için aşağıdaki dizi kullanılmaktadır:
String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
ORB orb=ORB.init(initORB,null);
Kullanılan (parametre, değer) çiftleri şunlardır:
("-ORBInitialHost",machine) : ce couple précise la machine ou opère l’annuaire des services CORBA, ici la machine passée en paramètre au serveur.
("-ORBInitialPort",port ) : ce couple précise le port ou opère l’annuaire des services CORBA, ici le port passé en paramètre au serveur.
init yönteminin ikinci parametresi null olarak bırakılmıştır. İlk parametre de null olarak bırakılmış olsaydı, kullanılan (makine, bağlantı noktası) çifti varsayılan olarak (localhost,900) olurdu.
10.2.5.2.3. Sunucuyu hizmet dizinine kaydetme CORBA
Sunucunun dizinine kaydı aşağıdaki işlemlerle gerçekleştirilir:
// hizmet, hizmetler dizinine ekleniyor
// adı srvEcho olacak
org.omg.CORBA.Object objRef=
orb.resolve_initial_references("NameService");
NamingContext ncRef=NamingContextHelper.narrow(objRef);
NameComponent nc= new NameComponent(nomService,"");
NameComponent path[]={nc};
// sunucu oluşturulur ve srvEcho hizmetiyle ilişkilendirilir
srvEcho serveurEcho=new srvEcho();
ncRef.rebind(path,serveurEcho);
orb.connect(serveurEcho);
Kodun ilk kısmı, hizmet adının hazırlanmasından oluşur. Bu ad, kodda path değişkeni ile temsil edilir. Bir hizmet adı birkaç bileşenden oluşur:
- objRef adlı başlangıç bileşeni; bu, NamingContext türüne dönüştürülmesi gereken genel bir nesnedir; burada ncRef.
- hizmet adı, burada sunucuya parametre olarak aktarılan nomService
Adın bu bileşenleri (NameComponent) bir dizide bir araya getirilir; burada path. Oluşturulan hizmeti kesin olarak “adlandıran” bu dizidir. Ad oluşturulduktan sonra geriye kalan
- sunucunun bir örneğiyle (daha önce oluşturulan srvEcho sınıfı) ilişkilendirmek kalır
srvEcho serveurEcho=new srvEcho();
- ve bunu dizinine kaydetmek
10.2.5.3. Sunucu başlatma sınıfının derlenmesi
Önceki sınıfı derliyoruz:
E:\data\java\corba\ECHO>j:\jdk12\bin\javac serveurEcho.java
E:\data\java\corba\ECHO>dir
ECHO IDL 78 15/03/99 13:56 ECHO.IDL
SERVEU~1 CLA 1 793 18/03/99 13:18 serveurEcho.class
SERVEU~1 JAV 1 806 16/03/99 15:38 serveurEcho.java
SRVECH~1 CLA 488 18/03/99 11:30 srvEcho.class
SRVECH~1 JAV 252 15/03/99 14:02 srvEcho.java
ECHO <REP> 17/03/99 17:19 echo
10.2.6. Müşterinin yazısı
10.2.6.1. Kod
Yankı hizmetimizi test etmek için bir istemci yazıyoruz. İstemciye, sunucuya verdiğimiz üç parametrenin aynısını vereceğiz:
Makine: CORBA hizmet dizinlerinin bulunduğu makine
Bağlantı noktası: Bu dizinin çalıştığı bağlantı noktası
nomService: yankı hizmetinin adı
İstemci, yankı hizmetine bağlanır ve ardından kullanıcıdan klavyeyle mesajlar yazmasını ister. Bu mesajlar yankı sunucusuna gönderilir ve sunucu da bunları geri gönderir. Bu diyalogun takibi ekranda yapılır.
Yankı hizmetinin CORBA istemcisi, daha önce yazılan RMI istemcisine çok benzemektedir. Burada da istemci, bağlanmak istediği sunucu nesnesinin referansını almak için bir dizin hizmetine bağlanmalıdır. İki istemci arasındaki fark, sadece ve sadece budur. İşte CORBA yankı istemcisinin kodu:
10.2.6.2. İstemcinin sunucuya bağlanması
Yukarıdaki CORBA istemcisi, şu komutla sunucuya bağlanır:
Bu işlemin ardından, istemci echo sunucusunun bir referansını elde eder. Bundan sonra, CORBA istemcisi ile RMI istemcisi arasında bir fark kalmaz. Sunucuya bağlantıyı sağlayan özel yöntem şöyledir:
// ithal edilen paketler
import java.io.*;
import echo.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
// ---------- cltEcho sınıfı
public class cltEcho {
public static void main(String arg[]){
// sözdizimi: cltEcho machineAnnuaire portAnnuaire hizmetadı
// makine: hizmet rehberinin çalıştığı makine CORBA
// bağlantı noktası: hizmet dizininin çalıştığı bağlantı noktası
// nomService: yankı hizmetinin adı
// argümanların doğrulanması
if(arg.length!=3){
System.err.println("Syntaxe : pg machineAnnuaire portAnnuaire nomservice");
System.exit(1);
}
// parametreler alınır
String machine=arg[0];
String port=arg[1];
String nomService=arg[2];
// yankı sunucusuyla bağlantı kuruluyor
iSrvEcho serveurEcho=getServeurEcho(machine,port,nomService);
// istemci-sunucu iletişimi
BufferedReader in=null;
String msg=null;
String reponse=null;
iSrvEcho serveur=null;
try{
// klavye akışının açılması
in=new BufferedReader(new InputStreamReader(System.in));
// yankı sunucusuna gönderilecek mesajları okuma döngüsü
System.out.print("Message : ");
msg=in.readLine().toLowerCase().trim();
while(! msg.equals("fin")){
// mesajın sunucuya gönderilmesi ve yanıtın alınması
reponse=serveurEcho.echo(msg);
// izleme
System.out.println("Réponse serveur : " + reponse);
// sonraki mesaj
System.out.print("Message : ");
msg=in.readLine().toLowerCase().trim();
}// while
// işlem tamamlandı
System.exit(0);
// hata yönetimi
} catch (Exception e){
System.err.println("Erreur : " + e);
System.exit(2);
}// try
}// main
// ---------------------- getServeurEcho
private static iSrvEcho getServeurEcho(String machine, String port,
String nomService){
// yankı sunucusundan referans ister
// takip
System.out.println("--> Connexion au serveur CORBA en cours...");
// yankı sunucusunun referans numarası
iSrvEcho serveurEcho=null;
try{
// çalışmak için CORBA nesnesi talep ediliyor
String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
ORB orb=ORB.init(initORB,null);
// yankı sunucusunu bulmak için dizin hizmeti kullanılıyor
org.omg.CORBA.Object objRef=
orb.resolve_initial_references("NameService");
NamingContext ncRef=NamingContextHelper.narrow(objRef);
// aranan hizmetin adı srvEcho'tir - bu hizmet talep ediliyor
NameComponent nc= new NameComponent(nomService,"");
NameComponent path[]={nc};
serveurEcho=iSrvEchoHelper.narrow(ncRef.resolve(path));
} catch (Exception e){
System.err.println("Erreur lors de la localisation du serveur d'écho ("
+ e + ")");
System.exit(10);
}// try-catch
// sunucuya referans veriliyor
return serveurEcho;
}// getServeurEcho
}// sınıf
Sunucudakiyle aynı kod dizileri karşımıza çıkıyor:
- ORB adlı bir nesne oluşturuyoruz; bu nesne, CORBA hizmet dizinine bağlanmamızı sağlayacak
String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
ORB orb=ORB.init(initORB,null);
- yankı hizmetinin adının çeşitli bileşenlerini tanımlıyoruz
org.omg.CORBA.Object objRef=orb.resolve_initial_references("NameService");
NamingContext ncRef=NamingContextHelper.narrow(objRef);
NameComponent nc= new NameComponent(nomService,"");
NameComponent path[]={nc};
- dizin hizmetinden yankı hizmetinin referansını talep ediyoruz (işte bu noktada sunucudan farklılık gösteriyoruz)
10.2.6.3. Compilation
E:\data\java\corba\ECHO>j:\jdk12\bin\javac cltEcho.java
E:\data\java\corba\ECHO>dir
CLTECH~1 CLA 2 599 18/03/99 13:51 cltEcho.class
CLTECH~1 JAV 2 907 16/03/99 16:15 cltEcho.java
ECHO IDL 78 15/03/99 13:56 ECHO.IDL
SERVEU~1 CLA 1 793 18/03/99 13:18 serveurEcho.class
SERVEU~1 JAV 1 806 16/03/99 15:38 serveurEcho.java
SRVECH~1 CLA 488 18/03/99 11:30 srvEcho.class
SRVECH~1 JAV 252 15/03/99 14:02 srvEcho.java
ECHO <REP> 17/03/99 17:19 echo
10.2.7. Testler
10.2.7.1. Dizin hizmetinin başlatılması
Bir Windows makinesinde, dizin hizmetini şu şekilde başlatıyoruz:
Bu komut, makinenin 1000 numaralı bağlantı noktasında dizin hizmetini başlatır.
tnameserv dizin hizmeti, aşağıdakine benzer bir ekran çıktısı üretir:
Initial Naming Context:
IOR:000000000000002849444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f
6e746578743a312e3000000000010000000000000030000100000000000a69737469612d30303900
044700000018afabcafe000000027620dd9a000000080000000000000000
TransientNameServer: setting port for initial object references to: 1000
Okunması biraz zor, ancak son satırı not edelim: hizmet 1000 numaralı bağlantı noktasında aktif.
10.2.7.2. Echo sunucusunun başlatılması
Echo hizmeti üç parametreyle başlatılır:
E:\data\java\corba\ECHO>start j:\jdk12\bin\java serveurEcho localhost 1000 srvEcho
Sunucu şunu görüntüler:
10.2.7.3. Sunucuyla aynı bilgisayarda istemcinin başlatılması
E:\data\java\corba\ECHO>j:\jdk12\bin\java cltEcho localhost 1000 srvEcho
--> Connexion au serveur CORBA en cours...
Message : msg1
Réponse serveur : [msg1]
Message : msg2
Réponse serveur : [msg2]
Message : fin
10.2.7.4. Sunucudan farklı bir Windows bilgisayarda istemcinin başlatılması
E:\data\java\corba\ECHO>j:\jdk12\bin\java cltEcho tahe.istia.univ-angers.fr 1000 srvEcho
--> Connexion au serveur CORBA en cours...
Message : abcd
Réponse serveur : [abcd]
Message : efgh
Réponse serveur : [efgh]
Message : fin
10.3. Örnek 2: bir SQL sunucusu
10.3.1. Giriş
Burada, daha önce Java bağlamında incelediğimiz SQL sunucusunun kodunu tekrar ele alıyoruz. RMI, her iki yöntemin ortak noktalarını ve farklılıklarını vurgulamak amacıyla. SQL sunucusunun işlevini hatırlatmak gerekirse: Bu sunucu bir Windows makinesinde bulunur ve uzak istemcilerin bu Windows makinesindeki ODBC genel veritabanlarını kullanmasına olanak tanır.

CORBA istemcisi 3 işlem gerçekleştirebilir:
- seçtiği veritabanına bağlanmak
- SQL sorguları gönderebilir
- bağlantıyı kapatmak
Sunucu, istemcinin SQL isteklerini yürütür ve sonuçları istemciye gönderir. Bu, sunucunun temel işlevidir ve bu nedenle ona SQL sunucusu diyoruz. Daha önce yankı sunucusu ile gördüğümüz çeşitli adımları burada da uygularız.
10.3.2. Sunucunun IDL arayüzünün yazılması
Hatırlatmak gerekirse, sunucu için kullandığımız RMI arayüzü şöyledir:
import java.rmi.*;
// uzak arayüz
public interface interSQL extends Remote{
public String connect(String pilote, String url, String id, String mdp)
throws java.rmi.RemoteException;
public String[] executeSQL(String requete, String separateur)
throws java.rmi.RemoteException;
public String close()
throws java.rmi.RemoteException;
}
Farklı yöntemlerin rolleri şu şekildeydi:
Connect: İstemci, uzak bir veritabanına bağlanır ve bu veritabanına erişmek için sürücüsünü, JDBC URL'sini, kimliğini (id) ve şifresini (mdp) belirtir. Sunucu, bağlantının sonucunu gösteren bir karakter dizisini istemciye döndürür:
executeSQL: İstemci, bağlı olduğu veritabanında SQL sorgusunun yürütülmesini ister. Geri gönderilen sonuçlarda alanları ayıracak karakteri belirtir. Sunucu, bir dizi karakter dizisi döndürür:
veritabanı güncelleme isteği için; burada n, güncellenen satır sayısını ifade eder
istek bir hata oluşturduysa
istek herhangi bir sonuç üretmediyse
sorgu sonuç ürettiğinde. Sunucu tarafından bu şekilde döndürülen satırlar, sorgunun sonuç satırlarıdır.
Close: İstemci, uzak veritabanıyla olan bağlantısını kapatır. Sunucu, bu kapatma işleminin sonucunu belirten bir dize döndürür:
Sunucunun IDL arayüzü şu şekilde olacaktır:
module srvSQL{
typedef sequence<string> resultats;
interface interSQL{
string connect(in string pilote, in string urlBase, in string id, in string mdp);
resultats executeSQL(in string requete, in string separateur);
string close();
};// arayüz
};// modül
Echo sunucusunun IDL arayüzünde gördüğümüzden tek fark, sequence anahtar sözcüğünün kullanılmasıdır. Bu anahtar sözcük, tek boyutlu bir dizi tanımlamaya olanak tanır. Tanımlama iki adımda yapılır:
- diziyi tanımlamak için bir tür belirleme, burada "resultats":
typedef anahtar sözcüğü, C/C++ programcıları tarafından iyi bilinir: bu anahtar sözcük, yeni bir tür tanımlamaya olanak tanır. Burada, resultats türü, sequence<string> türü olan c.a.d ile eşdeğer olarak tanımlanmıştır. Bu, dinamik (boyutu belirlenmemiş) bir karakter dizisi dizisidir.
- Yeni türün ihtiyaç duyulan yerlerde kullanımı
Dolayısıyla, executeSQL yöntemi bir karakter dizisi dizisi döndürür.
10.3.3. Sunucunun IDL arayüzünün derlenmesi
Önceki IDL arayüzü, srvSQL.idl dosyasına eklenir. Bu dosya derlenir:
E:\data\java\corba\sql>d:\javaidl\idltojava -fno-cpp srvSQL.idl
E:\data\java\corba\sql>dir
SRVSQL IDL 275 19/03/99 9:59 srvSQL.idl
SRVSQL <REP> 19/03/99 9:41 srvSQL
Derleme sonucunda, IDL (srvSQL) adlı arayüz modülünün adını taşıyan bir dizin oluşturulduğu görülmektedir. Bu dizinin içeriğine bir göz atalım:
E:\data\java\corba\sql>dir srvSQl
RESULT~1 JAV 833 19/03/99 10:00 resultatsHolder.java
RESULT~2 JAV 1 883 19/03/99 10:00 resultatsHelper.java
_INTER~1 JAV 2 474 19/03/99 10:00 _interSQLStub.java
INTERS~1 JAV 448 19/03/99 10:00 interSQL.java
INTERS~2 JAV 841 19/03/99 10:00 interSQLHolder.java
INTERS~3 JAV 1 855 19/03/99 10:00 interSQLHelper.java
_INTER~2 JAV 4 535 19/03/99 10:00 _interSQLImplBase.java
Helper ve Holder dosyalarının, uzaktan arayüzün yöntemlerinin giriş-çıkış parametreleri ve sonuçlarıyla ilişkili sınıflar olduğu hatırlatılmalıdır. srvSQL dizini, .idl dosyasında tanımlanan interSQL arayüzüyle ilgili tüm .java dosyalarını içerir. Ayrıca, IDL arayüzünde oluşturulan resultats türüyle ilgili dosyalar da bulunmaktadır.
interSQL.java dosyası, sunucumuzun arayüzüne ait Java dosyasıdır. Otomatik olarak oluşturulan dosyanın beklentilerimize uygun olup olmadığını kontrol etmek önemlidir. Oluşturulan interSQL.java dosyası şöyledir:
/* * Dosya: ./SRVSQL/INTERSQL.JAVA * Kaynak: SRVSQL.IDL * Tarih: 19 Mart 1999 Cuma 09:59:48 * Tarafından: D:\JAVAIDL\IDLTOJ~1.EXE Java IDL 1.2 18 Ağustos 1998 16:25:34 */
package srvSQL;
public interface interSQL
extends org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity {
String connect(String pilote, String urlBase, String id, String mdp)
;
String[] executeSQL(String requete, String separateur)
;
String close()
;
}
Görüldüğü gibi, RMI istemci-sunucu için kullanılan arayüzle aynı arayüze sahibiz. Dolayısıyla devam edebiliriz. Tüm bu .java dosyalarını derleyelim:
E:\data\java\corba\sql\srvSQL>j:\jdk12\bin\javac *.java
Note: _interSQLImplBase.java uses or overrides a deprecated API. Recompile with
"-deprecation" for details.
1 warning
E:\data\java\corba\sql\srvSQL>dir *.class
_INTER~1 CLA 3 094 19/03/99 10:01 _interSQLImplBase.class
_INTER~2 CLA 1 953 19/03/99 10:01 _interSQLStub.class
INTERS~1 CLA 430 19/03/99 10:01 interSQL.class
INTERS~2 CLA 2 096 19/03/99 10:01 interSQLHelper.class
INTERS~3 CLA 870 19/03/99 10:01 interSQLHolder.class
RESULT~1 CLA 2 047 19/03/99 10:01 resultatsHelper.class
RESULT~2 CLA 881 19/03/99 10:01 resultatsHolder.class
10.3.4. SQL sunucusunun kodu
Şimdi SQL sunucu kodunu yazıyoruz. Bu sınıfın, IDL dosyasının derlenmesi sonucu üretilen _nomInterfaceImplBase soyut sınıfından türetilmesi gerektiğini hatırlayalım. Bu özellik dışında ve hizmetin bir dizine kaydedilmesiyle ilgili kod dizileri hariç tutulduğunda, CORBA sunucusunun kodu, RMI sunucusunkiyle aynıdır:
// ithal edilen paketler
import java.sql.*;
import java.util.*;
import srvSQL.*;
// sınıf SQLServant
public class SQLServant extends _interSQLImplBase{
// sınıfın genel verileri
private Connection DB;
// --------------- bağlantı
public String connect(String pilote, String url, String id,
String mdp){
// sürücü aracılığıyla url veritabanına bağlantı
// id kimliği ve mdp şifresi ile kimlik doğrulama
String resultat=null; // yöntemin sonucu
try{
// sürücünün yüklenmesi
Class.forName(pilote);
// bağlantı isteği
DB=DriverManager.getConnection(url,id,mdp);
// tamam
resultat="200 Connexion réussie";
} catch (Exception e){
// hata
resultat="500 Echec de la connexion (" + e + ")";
}
// son
return resultat;
}
// ------------- executeSQL
public String[] executeSQL(String requete, String separateur){
// SQL sorgusunu DB veritabanında yürütür
// ve sonuçları bir dize dizisine yerleştiriyor
// sorgunun yürütülmesi için gerekli veriler
Statement S=null;
ResultSet RS=null;
String[] lignes=null;
Vector resultats=new Vector();
String ligne=null;
try{
// sorgu konteynerinin oluşturulması
S=DB.createStatement();
// sorgunun yürütülmesi
if (! S.execute(requete)){
// güncelleme sorgusu
// güncellenen satır sayısı döndürülür
lignes=new String[1];
lignes[0]="100 "+S.getUpdateCount();
return lignes;
}
// bu bir sorgu idi
// sonuçlar alınır
RS=S.getResultSet();
// Sonuç kümesindeki alan sayısı
int nbChamps=RS.getMetaData().getColumnCount();
// bunlar işlenir
while(RS.next()){
// sonuç satırının oluşturulması
ligne="101 ";
for (int i=1;i<nbChamps;i++)
ligne+=RS.getString(i)+separateur;
ligne+=RS.getString(nbChamps);
// sonuç vektörüne eklenir
resultats.addElement(ligne);
}// while
// sonuçların işlenmesi sona erdi
// kaynaklar serbest bırakılıyor
RS.close();
S.close();
// sonuçların döndürülmesi
int nbLignes=resultats.size();
if (nbLignes==0){
lignes=new String[1];
lignes[0]="501 Pas de résultats";
} else {
lignes=new String[resultats.size()];
for(int i=0;i<lignes.length;i++)
lignes[i]=(String) resultats.elementAt(i);
}//if
return lignes;
} catch (Exception e){
// hata
lignes=new String[1];
lignes[0]="500 " + e;
return lignes;
}// try-catch
}// executeSQL
// --------------- kapat
public String close(){
// veritabanı bağlantısını kapatır
String resultat=null;
try{
DB.close();
resultat="200 Base fermée";
} catch (Exception e){
resultat="500 Erreur à la fermeture de la base ("+e+")";
}
// sonucun döndürülmesi
return resultat;
}
}// SQLServant sınıfı
Bu sınıf, derlediğimiz SQLServant.java dosyasına yerleştirilmiştir:
E:\data\java\corba\sql>dir
SRVSQL IDL 275 19/03/99 9:59 srvSQL.idl
SRVSQL <REP> 19/03/99 9:41 srvSQL
SQLSER~1 JAV 2 941 15/03/99 9:09 SQLServant.java
E:\data\java\corba\sql>j:\jdk12\bin\javac SQLServant.java
E:\data\java\corba\sql>dir *.class
SQLSER~1 CLA 2 568 19/03/99 10:19 SQLServant.class
10.3.5. SQL sunucusunun başlatma programının yazılması
Yukarıdaki sınıf, SQL sunucusunun başlatıldıktan sonraki halini temsil eder. Bundan önce, sunucunun CORBA hizmet dizinine kaydedilmesi gerekir. Yankı hizmetinde olduğu gibi, bunu özel bir sınıf kullanarak yapacağız ve yürütme sırasında bu sınıfa üç parametre aktaracağız:
Makine: CORBA hizmet dizinlerinin bulunduğu makine
Bağlantı Noktası: Bu dizinin çalıştığı bağlantı noktası
nomService: SQL hizmetinin adı
Bu sınıfın kodu, yankı hizmeti için aynı işlevi gören sınıfın koduyla neredeyse aynıdır. İki sınıf arasındaki farkı büyük harflerle vurguladık: bu sınıf, aynı sunucu nesnesini oluşturmuyor. Dolayısıyla, sunucuyu başlatma mekanizmasının her zaman aynı olduğunu görüyoruz. Bu mekanizmayı burada yapıldığı gibi bir sınıfa ayırırsak, geliştirici için neredeyse görünmez hale gelir.
// ithal edilen paketler
import srvSQL.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
//----------- serveurSQL sınıfı
public class serveurSQL{
// ------- ana program: SQL sunucusunu başlatır
public static void main(String arg[]){
// serveurSQL makine bağlantı noktası hizmeti
//doğru sayıda argüman var mı
if(arg.length!=3){
System.err.println("Syntaxe : pg machineAnnuaireCorba portAnnuaireCorba nomService");
System.exit(1);
}
// argümanları alıyoruz
String machine=arg[0];
String port=arg[1];
String nomService=arg[2];
String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
try{
// çalışmak için bir nesneye ihtiyacımız var CORBA
ORB orb=ORB.init(initORB,null);
// hizmeti hizmet dizinine ekliyoruz
org.omg.CORBA.Object objRef=
orb.resolve_initial_references("NameService");
NamingContext ncRef=NamingContextHelper.narrow(objRef);
NameComponent nc= new NameComponent(nomService,"");
NameComponent path[]={nc};
// sunucuyu oluşturuyoruz ve srvSQL hizmetiyle ilişkilendiriyoruz
SQLServant serveurSQL=new SQLServant();
ncRef.rebind(path,serveurSQL);
orb.connect(serveurSQL);
// takip
System.out.println("Serveur SQL prêt");
// müşterilerden gelen istekleri bekleme
java.lang.Object sync=new java.lang.Object();
synchronized(sync){
sync.wait();
}
} catch(Exception e){
// bir hata oluştu
System.err.println("Erreur " + e);
e.printStackTrace(System.err);
}
}// bekleme
}// srvSQL
Bu yeni sınıfı derliyoruz:
E:\data\java\corba\sql>j:\jdk12\bin\javac serveurSQL.java
E:\data\java\corba\sql>dir *.class
SQLSER~1 CLA 2 568 19/03/99 10:19 SQLServant.class
SERVEU~1 CLA 1 800 19/03/99 10:33 serveurSQL.class
10.3.6. İstemci komutu
CORBA sunucusunun istemcisi aşağıdaki parametrelerle çağrılır:
makine: CORBA hizmet dizinlerinin bulunduğu makine
bağlantı noktası: bu dizinin çalıştığı bağlantı noktası
nomService: SQL hizmetinin adı
sürücü: SQL sunucusunun istenen veritabanını yönetmek için kullanması gereken sürücü
urlBase: yönetilecek veritabanının URL’si JDBC
id: müşterinin kimliği veya kimlik yoksa null
mdp: müşterinin şifresi; şifre yoksa null
ayırıcı: SQL sunucusunun, bir sorgunun sonuç satırlarındaki alanları ayırmak için kullanması gereken karakter
İşte olası parametrelerin bir örneği:
burada:
makine: CORBA hizmet dizinlerinin bulunduğu makine
bağlantı noktası: bu rehberin çalıştığı bağlantı noktası
srvSQL: srvSQL, CORBA sunucusunun adı SQL
sürücü: sun.jdbc.odbc.JdbcOdbcDriver, ODBC arayüzüne sahip veritabanları için kullanılan standart sürücü
urlBase: jdbc:odbc:articles, Windows makinesindeki ODBC adlı genel veritabanları listesinde bildirilen articles veritabanını kullanmak için
id: null, kimlik yok
şifre: null, şifre yok
ayırıcı: , sonuçlardaki alanlar virgülle ayrılacaktır
Yukarıdaki parametrelerle başlatıldığında, istemci aşağıdaki adımları izler:
- machine makinesine port bağlantı noktası üzerinden bağlanarak CORBA srvSQL hizmetini talep eder
- ürün veritabanına bağlanmayı talep eder
- kullanıcıdan klavyeden bir sorgu SQL girmesini ister
- bunu sunucuya gönderir: SQL
- sunucu tarafından gönderilen sonuçları ekrana görüntüler
- kullanıcıdan klavyeden bir sorgu SQL girmesini tekrar ister. Sorgu bittiğinde durur.
İstemcinin Java kodu aşağıdadır. Açıklamalar, kodu anlamak için yeterli olacaktır. Şu hususlara dikkat edilmelidir:
- kod, daha önce incelediğimiz RMI istemcisiyle aynıdır. Aradaki fark, dizin hizmetine yapılan istek sürecidir; bu süreç, getServeurSQL yönteminde ayrı olarak ele alınmıştır.
- getServeurSQL yöntemi, echo istemcisi için yazılan yöntemle aynıdır
Dolayısıyla şunu görüyoruz ki:
- bir CORBA istemcisi ile bir RMI istemcisi arasındaki tek fark, sunucuya bağlanma şeklidir
- bu yöntem, tüm CORBA istemcileri için aynıdır
import srvSQL.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import java.io.*;
public class clientSQL {
// sınıfın genel verileri
private static String syntaxe =
"syntaxe : cltSQL machine port service pilote urlBase id mdp separateur";
private static BufferedReader in=null;
private static interSQL serveurSQL=null;
public static void main(String arg[]){
// sözdizimi: cltSQL makine bağlantı noktası ayırıcı sürücü url kimlik şifre
// makine bağlantı noktası: iletişime geçilecek hizmet dizinindeki makine ve bağlantı noktası CORBA
// hizmet: hizmet adı
// sürücü: kullanılacak veritabanı için sürücü
// urlBase : kullanılacak veritabanının JDBC URL'si
// id: kullanıcı kimliği
// mdp: şifresi
// ayırıcı: sorgu sonuçlarındaki alanları ayıran dize
// argüman sayısının doğrulanması
if(arg.length!=8)
erreur(syntaxe,1);
// veritabanı bağlantı parametrelerini başlatma
String machine=arg[0];
String port=arg[1];
String service=arg[2];
String pilote=arg[3];
String urlBase=arg[4];
String id, mdp, separateur;
if(arg[5].equals("null")) id=""; else id=arg[5];
if(arg[6].equals("null")) mdp=""; else mdp=arg[6];
if(arg[7].equals("null")) separateur=" "; else separateur=arg[7];
// CORBA dizin hizmeti parametreleri
String[] initORB={"-ORBInitialHost",arg[0],"-ORBInitialPort",arg[1]};
// CORBA istemcisi - SQL sunucusundan referans isteniyor
interSQL serveurSQL=getServeurSQL(machine,port,service);
// istemci-sunucu diyaloğu
String requete=null;
String reponse=null;
String[] lignes=null;
String codeErreur=null;
try{
// klavye akışının açılması
in=new BufferedReader(new InputStreamReader(System.in));
// takip
System.out.println("--> Connexion à la base de données en cours");
// veritabanına ilk bağlantı talebi
reponse=serveurSQL.connect(pilote,urlBase,id,mdp);
// takip
System.out.println("<-- "+reponse);
// yanıt analizi
codeErreur=reponse.substring(0,3);
if(codeErreur.equals("500"))
erreur("Abandon sur erreur de connexion à la base",3);
// sunucuya gönderilecek isteklerin okunma döngüsü SQL
System.out.print("--> Requête : ");
requete=in.readLine().toLowerCase().trim();
while(! requete.equals("fin")){
// sunucuya isteğin gönderilmesi ve yanıtın alınması
lignes=serveurSQL.executeSQL(requete,separateur);
// izleme
afficheLignes(lignes);
// sonraki istek
System.out.print("--> Requête : ");
requete=in.readLine().toLowerCase().trim();
}// while
// takip
System.out.println("--> Fermeture de la connexion à la base de données distante");
// bağlantı sonlandırılıyor
reponse=serveurSQL.close();
// takip
System.out.println("<-- " + reponse);
// son
System.exit(0);
// hata yönetimi
} catch (Exception e){
erreur("Abandon sur erreur : " + e,2);
}// deneme
}// ana
// ----------- AfficheLignes
private static void afficheLignes(String[] lignes){
for (int i=0;i<lignes.length;i++)
System.out.println("<-- " + lignes[i]);
}// afficheLignes
// ------------ hata
private static void erreur(String msg, int exitCode){
// hata mesajı görüntüleniyor
System.err.println(msg);
// kaynakların serbest bırakılması (gerekirse)
try{
in.close();
serveurSQL.close();
} catch(Exception e){}
// çıkılıyor
System.exit(exitCode);
}// hata
// ---------------------- getServeurSQL
private static interSQL getServeurSQL(String machine, String port, String service){
// sunucudan referans isteniyor SQL
// makine: hizmet dizini makinesi CORBA
// bağlantı noktası: hizmet dizinindeki bağlantı noktası CORBA
// hizmet: talep edilecek CORBA hizmetinin adı
// izleme
System.out.println("--> Connexion au serveur CORBA en cours...");
// sunucu referansı SQL
interSQL serveurSQL=null;
// CORBA dizin hizmetinin parametreleri
String[] initORB={"-ORBInitialHost",machine,"-ORBInitialPort",port};
try{
// çalışmak için bir CORBA nesnesi talep ediliyor - bunun için bağlantı noktası aktarılıyor
// CORBA hizmet rehberinin dinleme bağlantı noktası
ORB orb=ORB.init(initORB,null);
// SQL sunucusunu bulmak için dizin hizmetini kullanıyoruz
org.omg.CORBA.Object objRef=
orb.resolve_initial_references("NameService");
NamingContext ncRef=NamingContextHelper.narrow(objRef);
// aranan hizmetin adı srvSQL'tir - bu hizmet talep edilir
NameComponent nc= new NameComponent(service,"");
NameComponent path[]={nc};
serveurSQL=interSQLHelper.narrow(ncRef.resolve(path));
} catch (Exception e){
System.err.println("Erreur lors de la localisation du serveur SQL ("
+ e + ")");
System.exit(10);
}// try-catch
// sunucuya referans veriliyor
return serveurSQL;
}// getServeurSQL
}// sınıf
İstemci sınıfını derleyelim:
E:\data\java\corba\sql>j:\jdk12\bin\javac clientSQL.java
E:\data\java\corba\sql>dir *.class
SQLSER~1 CLA 2 568 19/03/99 10:19 SQLServant.class
SERVEU~1 CLA 1 800 19/03/99 10:33 serveurSQL.class
CLIENT~1 CLA 3 774 19/03/99 10:45 clientSQL.class
Testlere hazırız.
10.3.7. Testler
10.3.7.1. Pré-requis
"Articles" adlı bir veritabanının ACCESS adlı sunucunun Windows makinesinde herkese açık olarak mevcut olduğu varsayılmaktadır:

Bu veritabanının yapısı şu şekildedir:
ad | tür |
code | 4 karakterlik ürün kodu |
nom | adı (karakter dizisi) |
prix | fiyatı (gerçek) |
stock_actu | mevcut stoğu (tamsayı) |
stock_mini | ürünün yeniden stoklanması gereken minimum stok miktarı (tamsayı) |
10.3.7.2. Rehber hizmetinin başlatılması
E:\data\java\corba\sql>start j:\jdk12\bin\tnameserv -ORBInitialPort 1000
Le service d’annuaire est lancé sur le port 1000. Il affiche dans une fenêtre DOS quelque chose du genre :
Initial Naming Context:
IOR:000000000000002849444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f
6e746578743a312e3000000000010000000000000030000100000000000a69737469612d30303900
052800000018afabcafe000000027693d3fd000000080000000000000000
TransientNameServer: setting port for initial object references to: 1000
10.3.7.3. SQL sunucusunun başlatılması
SQL sunucusu başlatılıyor:
DOS penceresinde şunlar görüntüleniyor:
10.3.7.4. Sunucuyla aynı makinede bir istemci başlatılıyor
Sunucuyla aynı makinede bir istemci kullanıldığında elde edilen sonuçlar şunlardır:
E:\data\java\corba\sql>j:\jdk12\bin\java clientSQL localhost 1000 srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null ,
--> Connexion au serveur CORBA en cours...
--> Connexion à la base de données en cours
<-- 200 Connexion réussie
--> Sorgu: select isim, stock_actu, stock_mini from articles
<-- 101 vélo,31,8
<-- 101 arc,9,8
<-- 101 canoé,7,7
<-- 101 fusil,9,8
<-- 101 skis nautiques,13,8
<-- 101 essai3,13,9
<-- 101 cachalot,6,6
<-- 101 léopard,7,7
<-- 101 panthère,7,7
--> Sorgu: articles tablosundan stock_mini<7 olanları sil
<-- 100 1
--> Sorgu: select isim, stock_actu, stock_mini from articles
<-- 101 vélo,31,8
<-- 101 arc,9,8
<-- 101 canoé,7,7
<-- 101 fusil,9,8
<-- 101 skis nautiques,13,8
<-- 101 essai3,13,9
<-- 101 léopard,7,7
<-- 101 panthère,7,7
--> Requête : fin
--> Fermeture de la connexion à la base de données distante
<-- 200 Base fermée
10.3.7.5. Sunucudan farklı bir makinede istemciyi başlatma
Aşağıda, sunucudan farklı bir makinede bir istemci kullanıldığında elde edilen sonuçlar yer almaktadır:
E:\data\java\corba\sql>j:\jdk12\bin\java clientSQL tahe.istia.univ-angers.fr 1000 srvSQL sun.jdbc.odbc.JdbcOdbcDriver jdbc:odbc:articles null null ,
--> Connexion au serveur CORBA en cours...
--> Connexion à la base de données en cours
<-- 200 Connexion réussie
--> Sorgu: select * from articles
<-- 101 a300,v_lo,1202,31,8
<-- 101 d600,arc,5000,9,8
<-- 101 d800,canoé,1502,7,7
<-- 101 x123,fusil,3000,9,8
<-- 101 s345,skis nautiques,1800,13,8
<-- 101 f450,essai3,3,13,9
<-- 101 z400,léopard,500000,7,7
<-- 101 g457,panthère,800000,7,7
--> Requête : fin
--> Fermeture de la connexion à la base de données distante
<-- 200 Base fermée
10.4. IDL - JAVA Eşleşmeleri
Burada, basit türler IDL ve JAVA arasındaki eşleşmeleri veriyoruz:
IDL türü | Java türü |
boolean | boolean |
char | char |
wchar | char |
bayt | byte |
dize | java.lang.String |
wstring | java.lang.String |
short | short |
işaretsiz kısa tamsayı | short |
long | int |
işaretsiz long | int |
long long | long |
işaretsiz uzun uzun | long |
float | float |
double | double |
IDL arayüzünde T türündeki elemanlardan oluşan bir dizi tanımlamak için şu komut kullanılır:
komutu kullanılır ve ardından dizinin türünü belirtmek için nomType kullanılır. Dolayısıyla, SQL sunucu arayüzünde şu bildirim kullanılmıştır:
kullanılmıştır; böylece resultats, Java'da String[] tablosunu işaret eder.