RMI dağıtık sistemlerdeki RPC (Remote Procedure Call) mantığına benzeyen ancak sadece Javaya özgü olan bir sistemdir.Bir makine üzerinde çalışan bir java nesnesinin başka bir makinede çalışan java nesnesine ait bir metodu çağırabilmesini sağlar.Bu da dağıtık uygulama geliştirmemizi sağlar.
Peki RMI kullanmanın geliştirici ve son kullanıcıya ne gibi getirileri vardır.Geliştirici açısından bakarsak uygulama geliştirme sırasında ağ işlemlerinin alt düzey ayrıntıları ile uğraşmasına gerek kalmamaktadır.Son kullanıcı açısından bakarsak da, kullanıcıya üst düzey bir arayüz sunmaktadır.
İsterseniz konunun daha iyi anlaşılması açısından basit bir uygulama yapalım :
server.java
package rmi;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.rmi.AccessException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class server extends UnicastRemoteObject implements arayüz {
Registry kayit;
String adres;
int port;
public server() throws RemoteException
{
super();
try{
adres=(InetAddress.getLocalHost().toString());
}
catch(UnknownHostException ex)
{
System.out.println(ex);
}
port=1316;
try
{
kayit=LocateRegistry.createRegistry(port);
}
catch(RemoteException ex)
{
System.out.println(ex);
}
try {
kayit.rebind("Local Interface", this);
} catch (AccessException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void mesajAl(String mesaj) throws RemoteException
{
System.out.println(mesaj);
}
public static void main(String[] args) {
try {
server obj=new server();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
client.java
package rmi;
import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import javax.swing.JOptionPane;
public class client {
Registry kayit=null;
arayüz objArayüz=null;
public client()
{
String mesajgir=JOptionPane.showInputDialog("Bir mesaj girin");
try
{
kayit=LocateRegistry.getRegistry("127.0.0.1",1316);
}
catch(RemoteException ex)
{
System.out.println(ex);
}
try{
objArayüz=(arayüz)(kayit.lookup("Local Interface"));
}
catch(AccessException ex)
{
System.out.println(ex);
}
catch(RemoteException ex)
{
System.out.println(ex);
}
catch(NotBoundException ex)
{
System.out.println(ex);
}
try
{
objArayüz.mesajAl(mesajgir);
}
catch(RemoteException ex)
{
System.out.println(ex);
}
}
public static void main(String[] args) {
client objClient=new client();
}
}
arayüz.java
package rmi;
import java.rmi.RemoteException;
import java.rmi.Remote;
public interface arayüz extends Remote {
public void mesajAl(String mesaj) throws RemoteException;
}
Uygulamada client nesnesi server sınıfınının mesajAl() metodunu "arayüz" arayüzü aracılığıyla çağırmaktadır.
Gördüğünüz gibi kullanımı oldukça kolay.Kullanımının kolaylığı,taşınabilir olması,güvenilir olması RMI ın dağıtık uygulamalarda tercih edilme sebepleri arasında geliyor.
24 Kasım 2010 Çarşamba
9 Kasım 2010 Salı
J2ME - RMS ( RECORD MANAGEMENT SYSTEM )
J2ME uygulamalarımızda verimizi depolamak ve sonra gerektiğinde yeniden ulaşmak istediğimizde MIDP nin bize sunduğu RMS adı verilen paketi kullanırız.
RMS verileri Record Store adı verilen alanlarda saklar.Daha anlaşılır olabilmesi için bu alanları veritabanı uygulamalarındaki tablolar gibi düşünebiliriz.Bu alanlar kayıtlardan oluşmaktadır.Kayıtlar ise veri alanlarından.Az önceki veri tabanı tablosu örneğini düşünürsek kayıtları satırlara ,bu kayıtlardaki veri alanlarını ise sütunlara benzetebiliriz.Şimdi isterseniz kayıt alanları nasıl oluşturulur,veri nasıl yazılır,nasıl okunur bunlara bakalım :
Kayıt Alanı Açmak
Kayıt alanı açmak için openRecordStore() metodu kullanılır.Bu metod ile yeni bir kayıt alanı oluşturabilir ya da var olan bir alanı açabiliriz.
RecordStore openRecordStore(String recordStoreName , boolean createIfNecessary)
String recordStoreName : kayıt alanının ismi
boolean createIfNecessary : true ise kayıt alanı mevcutsa açar , yoksa yeni alan açar.
false ise kayıt alanı mevcutsa açar değilse yenisini yaratmaz.
Kayıt Alanını Kapatmak
Bunun için ise closeRecordStore() metodu kullanılır.Bu metod herhangi bir parametre almaz.
void closeRecordStore()
Kayıt Alanına Veri Yazmak
Veri yazmak için addRecord() metodu kullanılır.
int addRecord(byte [] data , int offset , int numBytes)
byte [] data : yazılacak verinin byte dizisi
int offset : byte dizisinin ilk bytenın indeksi
int numBytes : yazılacak toplam byte değeri
Int türünde olan Return değeri ise kaydın id sidir. (Burada kaydın id si olarak kastettiğim şey yaratılan her bir kayıt için oluşturulan id değeridir.Bu değer kaydımızın primary keyidir.)
Kayıt Alanından Veri Okumak
Bunun için ise getRecord() metodu kullanılmaktadır.
byte getRecord(int recordId)
int recordId : okunacak kaydın idsi.
Metod kaydı byte dizisi şeklinde geri döndürür.
int getRecord(int recordİd , byte [] buffer , int offset)
byte [] buffer : kaydın yazılacağı buffer dizisi
int offset : kayıt alanındaki byte dizisinin kaçıncı byteından itibaren okunacağı bilgisi
Şimdi isterseniz gelin bu anlattıklarımızı bir uygulama üzerinde görelim :
package hello;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
import java.io.*;
/**
* @author aycan
*/
public class HelloMIDlet extends MIDlet implements CommandListener {
private boolean midletPaused = false;
private Command exitCommand;
private Form form;
private StringItem stringItem;
private Command process;
private Alert alert;
private RecordStore recordStore = null;
/**
* The HelloMIDlet constructor.
*/
public HelloMIDlet() {
}
private void initialize() {
getForm().addCommand(getProcess());
getForm().addCommand(getExitCommand());
getForm().setCommandListener(this);
}
/**
* Performs an action assigned to the Mobile Device - MIDlet Started point.
*/
public void startMIDlet() {
// write pre-action user code here
switchDisplayable(null, getForm());
// write post-action user code here
}
/**
* Performs an action assigned to the Mobile Device - MIDlet Resumed point.
*/
public void resumeMIDlet() {
}
/**
* Switches a current displayable in a display. The
* @param alert the Alert which is temporarily set to the display; if
* @param nextDisplayable the Displayable to be set
*/
public void switchDisplayable(Alert alert, Displayable nextDisplayable) {
// write pre-switch user code here
Display display = getDisplay();
if (alert == null) {
display.setCurrent(nextDisplayable);
} else {
display.setCurrent(alert, nextDisplayable);
}
// write post-switch user code here
}
/**
* Called by a system to indicated that a command has been invoked on a particular displayable.
* @param command the Command that was invoked
* @param displayable the Displayable where the command was invoked
*/
public void commandAction(Command command, Displayable displayable) {
// write pre-action user code here
if (displayable == form) {
if (command == exitCommand) {
// write pre-action user code here
exitMIDlet();
// write post-action user code here
}
}
if (command == getProcess()) {
createRecordStore();
writeRecordStore();
readRecordStore();
closingRecordStore();
deleteRecord();
} else if (command == getExitCommand()) {
destroyApp(false);
notifyDestroyed();
}
}
//
public Command getProcess() {
if (process == null) {
process = new Command("Process", Command.OK, 4);
}
return process;
}
/**
* Returns an initiliazed instance of exitCommand component.
* @return the initialized component instance
*/
public Command getExitCommand() {
if (exitCommand == null) {
exitCommand = new Command("Exit", Command.EXIT, 0);
}
return exitCommand;
}
/**
* Returns an initiliazed instance of form component.
* @return the initialized component instance
*/
public Form getForm() {
if (form == null) {
// write pre-init user code here
form = new Form("Welcome", new Item[] { getStringItem() });
form.addCommand(getExitCommand());
form.setCommandListener(this);
// write post-init user code here
}
return form;
}
/**
* Returns an initiliazed instance of stringItem component.
* @return the initialized component instance
*/
public StringItem getStringItem() {
if (stringItem == null) {
// write pre-init user code here
stringItem = new StringItem("Hello", "Hello, World!");
// write post-init user code here
stringItem.setLabel("Rms Çalışması");
stringItem.setText("");
}
return stringItem;
}
/**
* Returns a display instance.
* @return the display instance.
*/
public Display getDisplay() {
return Display.getDisplay(this);
}
/**
* Exits MIDlet.
*/
public void exitMIDlet() {
switchDisplayable(null, null);
destroyApp(true);
notifyDestroyed();
}
/**
* Called when MIDlet is started.
* Checks whether the MIDlet have been already started and initialize/starts or resumes the MIDlet.
*/
public void startApp() {
if (midletPaused) {
resumeMIDlet();
} else {
initialize();
startMIDlet();
}
midletPaused = false;
}
/**
* Called when MIDlet is paused.
*/
public void pauseApp() {
midletPaused = true;
}
/**
* Called to signal the MIDlet to terminate.
* @param unconditional if true, then the MIDlet has to be unconditionally terminated and all resources has to be released.
*/
public void destroyApp(boolean unconditional) {
}
}
Kodu çalıştırıp Process Commandına bastığımızda ekranımız şu şekilde olacaktır :
RMS verileri Record Store adı verilen alanlarda saklar.Daha anlaşılır olabilmesi için bu alanları veritabanı uygulamalarındaki tablolar gibi düşünebiliriz.Bu alanlar kayıtlardan oluşmaktadır.Kayıtlar ise veri alanlarından.Az önceki veri tabanı tablosu örneğini düşünürsek kayıtları satırlara ,bu kayıtlardaki veri alanlarını ise sütunlara benzetebiliriz.Şimdi isterseniz kayıt alanları nasıl oluşturulur,veri nasıl yazılır,nasıl okunur bunlara bakalım :
Kayıt Alanı Açmak
Kayıt alanı açmak için openRecordStore() metodu kullanılır.Bu metod ile yeni bir kayıt alanı oluşturabilir ya da var olan bir alanı açabiliriz.
RecordStore openRecordStore(String recordStoreName , boolean createIfNecessary)
String recordStoreName : kayıt alanının ismi
boolean createIfNecessary : true ise kayıt alanı mevcutsa açar , yoksa yeni alan açar.
false ise kayıt alanı mevcutsa açar değilse yenisini yaratmaz.
Kayıt Alanını Kapatmak
Bunun için ise closeRecordStore() metodu kullanılır.Bu metod herhangi bir parametre almaz.
void closeRecordStore()
Kayıt Alanına Veri Yazmak
Veri yazmak için addRecord() metodu kullanılır.
int addRecord(byte [] data , int offset , int numBytes)
byte [] data : yazılacak verinin byte dizisi
int offset : byte dizisinin ilk bytenın indeksi
int numBytes : yazılacak toplam byte değeri
Int türünde olan Return değeri ise kaydın id sidir. (Burada kaydın id si olarak kastettiğim şey yaratılan her bir kayıt için oluşturulan id değeridir.Bu değer kaydımızın primary keyidir.)
Kayıt Alanından Veri Okumak
Bunun için ise getRecord() metodu kullanılmaktadır.
byte getRecord(int recordId)
int recordId : okunacak kaydın idsi.
Metod kaydı byte dizisi şeklinde geri döndürür.
int getRecord(int recordİd , byte [] buffer , int offset)
byte [] buffer : kaydın yazılacağı buffer dizisi
int offset : kayıt alanındaki byte dizisinin kaçıncı byteından itibaren okunacağı bilgisi
Şimdi isterseniz gelin bu anlattıklarımızı bir uygulama üzerinde görelim :
package hello;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
import java.io.*;
/**
* @author aycan
*/
public class HelloMIDlet extends MIDlet implements CommandListener {
private boolean midletPaused = false;
private Command exitCommand;
private Form form;
private StringItem stringItem;
private Command process;
private Alert alert;
private RecordStore recordStore = null;
/**
* The HelloMIDlet constructor.
*/
public HelloMIDlet() {
}
private void createRecordStore() {
try {
recordStore = javax.microedition.rms.RecordStore.openRecordStore("myRecordStore",
true);
} catch (Exception e) {
alert = new Alert("Kayıt Yaratılırken Hata Oluştu", e.toString(), null, AlertType.WARNING);
alert.setTimeout(Alert.FOREVER);
getDisplay().setCurrent(alert);
}
}
private void writeRecordStore() {
try {
byte[] byteArray;
String name = "Ayşe Çalışkan";
int number = 20061001;
boolean outputBoolean = true;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
DataOutputStream outputDataStream = new DataOutputStream(outputStream);
outputDataStream.writeUTF(name);
outputDataStream.writeInt(number);
outputDataStream.writeBoolean(outputBoolean);
outputDataStream.flush();
byteArray = outputStream.toByteArray();
recordStore.addRecord(byteArray, 0, byteArray.length);
outputStream.reset();
outputStream.close();
outputDataStream.close();
} catch (Exception e) {
alert = new Alert("Kayit Yazarken Hata Olustu", e.toString(), null, AlertType.WARNING);
alert.setTimeout(Alert.FOREVER);
getDisplay().setCurrent(alert);
}
}
private void readRecordStore() {
try {
String name = null;
int number = 0;
boolean inputBoolean = false;
byte[] byteInputData = new byte[200];
ByteArrayInputStream inputStream = new ByteArrayInputStream(byteInputData);
DataInputStream inputDataStream = new DataInputStream(inputStream);
for (int x = 1; x <= recordStore.getNumRecords(); x++) {
recordStore.getRecord(x, byteInputData, 0);
name = inputDataStream.readUTF();
number = inputDataStream.readInt();
inputBoolean = inputDataStream.readBoolean();
inputStream.reset();
}
inputStream.close();
inputDataStream.close();
alert = new Alert("Reading", "Adı : " + name + "\nNumarası : " + number + "\n" +
inputBoolean, null, AlertType.WARNING);
alert.setTimeout(Alert.FOREVER);
getDisplay().setCurrent(alert);
} catch (Exception e) {
alert = new Alert("Kayıt Okurken Hata Oluştu", e.toString(), null, AlertType.WARNING);
alert.setTimeout(Alert.FOREVER);
getDisplay().setCurrent(alert);
}
}
private void closingRecordStore() {
try {
recordStore.closeRecordStore();
} catch (Exception error) {
alert = new Alert("Kayıt Alanı Kapatılırken Hata Oluştu", error.toString(), null,
AlertType.WARNING);
alert.setTimeout(Alert.FOREVER);
getDisplay().setCurrent(alert);
}
}
private void deleteRecord() {
if (javax.microedition.rms.RecordStore.listRecordStores() != null) {
try {
javax.microedition.rms.RecordStore.deleteRecordStore("myRecordStore");
} catch (Exception error) {
alert = new Alert("Kayıt Alanı Silinirken Hata Oluştu",
error.toString(), null, AlertType.WARNING);
alert.setTimeout(Alert.FOREVER);
getDisplay().setCurrent(alert);
}
}
}
private void initialize() {
getForm().addCommand(getProcess());
getForm().addCommand(getExitCommand());
getForm().setCommandListener(this);
}
/**
* Performs an action assigned to the Mobile Device - MIDlet Started point.
*/
public void startMIDlet() {
// write pre-action user code here
switchDisplayable(null, getForm());
// write post-action user code here
}
/**
* Performs an action assigned to the Mobile Device - MIDlet Resumed point.
*/
public void resumeMIDlet() {
}
/**
* Switches a current displayable in a display. The
display
instance is taken from getDisplay
method. This method is used by all actions in the design for switching displayable.* @param alert the Alert which is temporarily set to the display; if
null
, then nextDisplayable
is set immediately* @param nextDisplayable the Displayable to be set
*/
public void switchDisplayable(Alert alert, Displayable nextDisplayable) {
// write pre-switch user code here
Display display = getDisplay();
if (alert == null) {
display.setCurrent(nextDisplayable);
} else {
display.setCurrent(alert, nextDisplayable);
}
// write post-switch user code here
}
/**
* Called by a system to indicated that a command has been invoked on a particular displayable.
* @param command the Command that was invoked
* @param displayable the Displayable where the command was invoked
*/
public void commandAction(Command command, Displayable displayable) {
// write pre-action user code here
if (displayable == form) {
if (command == exitCommand) {
// write pre-action user code here
exitMIDlet();
// write post-action user code here
}
}
if (command == getProcess()) {
createRecordStore();
writeRecordStore();
readRecordStore();
closingRecordStore();
deleteRecord();
} else if (command == getExitCommand()) {
destroyApp(false);
notifyDestroyed();
}
}
//
public Command getProcess() {
if (process == null) {
process = new Command("Process", Command.OK, 4);
}
return process;
}
/**
* Returns an initiliazed instance of exitCommand component.
* @return the initialized component instance
*/
public Command getExitCommand() {
if (exitCommand == null) {
exitCommand = new Command("Exit", Command.EXIT, 0);
}
return exitCommand;
}
/**
* Returns an initiliazed instance of form component.
* @return the initialized component instance
*/
public Form getForm() {
if (form == null) {
// write pre-init user code here
form = new Form("Welcome", new Item[] { getStringItem() });
form.addCommand(getExitCommand());
form.setCommandListener(this);
// write post-init user code here
}
return form;
}
/**
* Returns an initiliazed instance of stringItem component.
* @return the initialized component instance
*/
public StringItem getStringItem() {
if (stringItem == null) {
// write pre-init user code here
stringItem = new StringItem("Hello", "Hello, World!");
// write post-init user code here
stringItem.setLabel("Rms Çalışması");
stringItem.setText("");
}
return stringItem;
}
/**
* Returns a display instance.
* @return the display instance.
*/
public Display getDisplay() {
return Display.getDisplay(this);
}
/**
* Exits MIDlet.
*/
public void exitMIDlet() {
switchDisplayable(null, null);
destroyApp(true);
notifyDestroyed();
}
/**
* Called when MIDlet is started.
* Checks whether the MIDlet have been already started and initialize/starts or resumes the MIDlet.
*/
public void startApp() {
if (midletPaused) {
resumeMIDlet();
} else {
initialize();
startMIDlet();
}
midletPaused = false;
}
/**
* Called when MIDlet is paused.
*/
public void pauseApp() {
midletPaused = true;
}
/**
* Called to signal the MIDlet to terminate.
* @param unconditional if true, then the MIDlet has to be unconditionally terminated and all resources has to be released.
*/
public void destroyApp(boolean unconditional) {
}
}
Kodu çalıştırıp Process Commandına bastığımızda ekranımız şu şekilde olacaktır :
Kaynaklar :
oracle.com
tutorials.jenkov.com
Kaydol:
Kayıtlar (Atom)