20 Eylül 2019 Cuma

RMI Remote Arayüzü

Giriş
Şu satırı dahil ederiz
import java.rmi.Remote;
import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject;
Bu arayüzden kalıtan sınıflar uzaktaki bir bilgisayardan çağrılabilir. 

Kullanım
Önce bir arayüz tanımlarız. Buna "Defining the Contract" deniliyor
public interface FooService extends Remote {
  void bar() throws RemoteException;
}
Açıklaması şöyle
This interface extends the java.rmi.Remote marker interface.
In addition, each method declared in the interface throws the java.rmi.RemoteException:
Note, though, that RMI supports the full Java specification for method signatures, as long as the Java types implement java.io.Serializable.
Daha sonra bu arayüzü gerçekleştiren sınıfı yazarız
public class FooServiceImpl implements FooService {
public bar() {...}
}
Açıklaması şöyle
Notice, that we've left off the throws RemoteException clause from the method definition.

It'd be unusual for our remote object to throw a RemoteException since this exception is typically reserved for the RMI library to raise communication errors to the client.

Leaving it out also has the benefit of keeping our implementation RMI-agnostic.
Tüm Kod
Bu servisi başlatmak ve durdurmak için şöyle yaparız. Burada kodun Foo sınıfı içinde olduğunu varsaydık. Server sınıfımız UnicastRemoteObject sınıfından kalıtmadığı için UnicastRemoteObject.exportObject() çağrısı yapma gerekti.
Registry registry;
int port = 52100;
String BINDING_NAME = "Foo";

public void startService() {
  FooService foo = (FooService) UnicastRemoteObject.exportObject(this,0);
  try {
    registry = LocateRegistry.createRegistry(port);
  } catch (Exception e){
    ...
  }

  registry.rebind (BINDING_NAME,foo);

}

public void stopService() {
  try {
    UnicastRemoteObject.unexportObject(this,true);
    registry.unbind(BINDING_NAME);
  } catch (NoSuchObjectException | NotBoundtException | AccessException e){
...
  }
}
Creating Stub
Eğer bir başka sınıfta kodlasaydık şöyle yaparız
FooService server = new FooServiceImpl();
FooService stub = (FooService) UnicastRemoteObject.exportObject(server, 0);
Açıklaması şöyle
We use the static UnicastRemoteObject.exportObject method to create our stub implementation. The stub is what does the magic of communicating with the server over the underlying RMI protocol.

The first argument to exportObject is the remote server object.

The second argument is the port that exportObject uses for exporting the remote object to the registry.

Giving a value of zero indicates that we don't care which port exportObject uses, which is typical and so chosen dynamically.

Unfortunately, the exportObject() method without a port number is deprecated.
Creating a Registry
Şöyle yaparız
Registry registry = LocateRegistry.createRegistry(52100);
Açıklaması şöyle. Burada Registry server stub'ın çalışacağı bilgisayarda
We can stand up a registry local to our server or as a separate stand-alone service.

For simplicity, we'll create one that is local to our server:

Also, we've used the createRegistry method, since we are creating the registry local to the server.

By default, an RMI registry runs on port 1099. Rather, a different port can also be specified in the createRegistry factory method.

But in the stand-alone case, we'd call getRegistry, passing the hostname and port number as parameters.
Binding the Stub
Şöyle yaparız
registry.rebind("MessengerService", stub);
Açıklaması şöyle. Burada Registry server stub'ın çalışacağı bilgisayarda
An RMI registry is a naming facility like JNDI etc. 
...
As a result, the remote object is now available to any client that can locate the registry.
Creating the Client
Şöyle yaparız
Registry registry = LocateRegistry.getRegistry();

MessengerService server = (MessengerService) registry.lookup("MessengerService");

String responseMessage = server.sendMessage("Client Message");

String expectedMessage = "Server Message";
 
assertEquals(expectedMessage, responseMessage);
Açıklaması şöyle. Burada Registry server stub'ın çalışacağı bilgisayarda
Because we're running the RMI registry on the local machine and default port 1099, we don't pass any parameters to getRegistry.

Indeed, if the registry is rather on a different host or different port, we can supply these parameters.

Once we lookup the stub object using the registry, we can invoke the methods on the remote server.
RMI Sunucusunun Her Bir Bağlanan Client'ı Tetiklemesi
Her client UnicastRemoteObject sınıfından ve IFooClient tarzı bir arayüzü gerçekleştirirse, client kendisini sunucuya gönderir ve sunucu IFooClient listesi tutar. Bu listedeki her nesneyi periyodik olarak tetiklerse, client'ın ayakta olup olmadığını anlar. Client'ı tetiklemek için de IFooClient'a ait bir metodu çağırır.

Hiç yorum yok:

Yorum Gönder