# RMI Struktur



## Guest (14. Nov 2007)

Hallo ,

ich habe mal ein Anliegen zu RMI . Ich arbeite ohne STUB und SKELETON. 
Mein RMI Server läuft eigentlich nur mit nachstehenden Code


```
try{
		
		LocateRegistry.createRegistry(Registry.REGISTRY_PORT); 
			
			//Remote Object erzeugen
			Remote service = new RemoteImpl();
			Naming.rebind("RemoteKommunikation", service);
		   }
		   catch(Exception ex)
		   {
			ex.printStackTrace();
			System.out.print("Registry Fehler"); 
		   }
		System.out.print("Server gestartet"); 
	}
```

Hier wird die Registry programmatisch gestartet und ein Objekt gebunden.
Frage 1: Muss ich diesen Code in einer Main Methode aufufen, wenn ich eine Client
Server Architektur einsetze?


Frage 2: Ich habe einen Datenbankcontroller , der die Datenbankschnittstelle bereithält.
Hier sind Funktionen wie  dbConnect() drin oder loadJDBCDriver() zum laden des DBTreibers,
aber auch execute oder DeleteQuerys...

Sollte man hier nicht den Server von dem DBController trennen?

Es wäre ja merkwürdig, in einem Controller eine Main Methode zu haben..

Danke

VG


----------



## Guest (14. Nov 2007)

1) Nein. Du kannst es initialisieren, wo es dir passt.
2) Betrachte alle Objekte, die du in der Registry bindest, als Facade- bzw. Service-Objekte. Sie sollten den Aufruf 
nur an die Bussiness Logik delegieren, selbst aber strohdoof sein (beschränkt auf Exception-Handling). Auf diese 
Art kannst du eine komplette Anwendung zuerst ohne RMI entwickeln und die RMI-Schicht hinterher einbauen.


----------



## Guest (15. Nov 2007)

Vielen Dank erst einmal. Das sind schon einmal wichtige Hinweise.

Ist es so gemeint, dass ich einfach irgendwann, wenn alles läuft einen Server als Fassade vor das System setze?

z.B.


```
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;

public class RemoteImpl extends UnicastRemoteObject implements RMIRemote{
	
DBController control;


public  RemoteImpl (DBController control) throws RemoteException{

this.DBController = control;

}

//nun die Methode aus dem Interface
```


loadJDBCDriver() 

connectDB();   wären nur noch teil einer Methode sendData(){};  ??


Würde mich freuen, hierauf ein Kommentar zu erhalten. Es wäre sehr wichtig für mich und mein Verständnis.

Danke


----------



## Guest (15. Nov 2007)

Anonymous hat gesagt.:
			
		

> Ist es so gemeint, dass ich einfach irgendwann, wenn alles läuft einen Server als Fassade vor das System setze?


Erstelle zuerst paar Interfaces.

z.B. (allerdings mit Kommentaren etc. )
	
	
	
	





```
public interface ISBNService
{
   BookInfo getBookInfo(String isbn) throws ServiceException;
}
```
dann eine simple Implementierung, wobei die Datenzugriffsschicht getrennt sein
sollte (übersichtlicher, austauschbar...)


```
protected class ISBNServiceImpl implements ISBNService
{
   public ISBNServiceImpl()
   {
   }

   public BookInfo getBookInfo(String isbn) throws ServiceException
   {
      try
      {
         // Anhand der Klasse (hier Interface ISBNServiceDao) wird eine Implementierung
         // der Dao-Schicht instanziiert und initialisiert.
         ISBNServiceDao dao = DaoFactory.createDao(ISBNServiceDao.class);
         BookInfo bookInfo = dao.getBookInfoByISBN(isbn);
         return bookInfo;
      }
      catch(DaoException e)
      {
         // Exceptions der Dao Schicht hier abfangen und in eine ServiceException konvertieren.
         // Diese sollte keine Details wie Stacktrace, die DaoException selbst etc. enthalten,
         // sondern Informationen, mit denen ein Normalsterblicher was anfangen kann.
         // Fehlercode, Fehlermeldung etc. sind schon mal nicht schlecht.
         // Die Ursache der Exceptions sollte bereits in der Dao-Schicht (mit den übergebenen Argumenten)
         // geloggt worden sein, damit du später einen Fehler nachvollziehen kannst.
         // Grundsätzlich gilt: Fehler dort loggen, wo sie auftauchen und das nur einmal.
         throw ExceptionFactory.createServiceException(this, e);
      }
   }
}
```
Wie du siehst, ist hier zunächst mal rein gar nix mit RMI.
Später kommt die Remote-Implementierung, die den Code oben wieder verwendet und ein Proxy, der das
Interface ISBNService implementiert und alles an die Serverschicht delegiert.

(z.B. Beachte den Unterschied. Es ist NICHT das gleiche Interface, sondern eine Kopie mit etwas RMI-Lametta)
	
	
	
	





```
public interface ISBNServiceRemote extends Remote
{
   BookInfo getBookInfo(String isbn) throws ServiceException, RemoteException;
}

protected class ISBNServiceRemoteImpl extends UnicastRemoteObject implements ISBNServiceRemote
{
   private static final long serialVersionUID = ...; // <-- nicht vergessen
   private ISBNService service;  <-- Hier das ursprüngliche Interface

   public ISBNServiceRemoteImpl() throws RemoteException
   {
      super();
   }

   public BookInfo getBookInfo(String isbn) throws ServiceException, RemoteException
   {
      BookInfo bookInfo = getService().getBookInfo(isbn);
      return bookInfo;
   }

   private ISBNService getService()
   {
      if(null == service)
      {
         // Hier wird die ursprüngliche Implementierung von ISBNService wieder verwendet,
         // allerdings auf dem Server.
         service = new ISBNServiceImpl();
      }
      return service;
   }
}

// Beachte, dass es das gleiche Interface ist, wie oben, während du noch kein RMI verwendet hast.
public class ISBNServiceProxy implements ISBNService
{
   public ISBNServiceProxy()
   {
   }

   public BookInfo getBookInfo(String isbn) throws ServiceException
   {
      try
      {
         ISBNServiceRemote service = getService(); // Verbindung zum Server, wenn nicht bereits geschehen
         BookInfo bookInfo = service.getBookInfo(isbn);
         return bookInfo;
      }
      catch(RemoteException e)
      {
         error(this, e); // Fehler loggen
         throw ExceptionFactory.createServiceException(this, e);
      }
   }

   ... Verbindung zum Server etc.
}
```

Clientseitig programmierst du dann gegen das Interface 'ISBNService' und die Implementierung interessiert 
dich nicht die Bohne.  :wink: 



> loadJDBCDriver()
> 
> connectDB();   wären nur noch teil einer Methode sendData(){};  ??


So ungefähr. Den Treiber brauchst du nur einmalig zu laden (von mir aus in main des Servers) und Connections kannst du in einem ConnectionPool verwalten.


----------

