Package switching

datafiddler

Mitglied
Szenario:
In einem package my.client werden Objekte/Methoden in einem package my.basepack verwendet.
my.basepack gibt es in zwei Varianten a) direkt b) via RMI.

Im RMI - Fall gibt es einen RMI Server, der selbst Variante basepack (direkt) verwendet, und ein Interface remote.basepack implementiert. Ein Client package verwendet remote.basepack, um damit für my.client my.basepack (via RMI) zu implementieren.

Je nach classpath bzw. Zusammenstellung des jar files wird die eine oder die andere Variante verwendet.

Der Grund: basepack läuft nur auf Windows (mit JNI Komponenten) , client soll plattformunabhängig sein, aber wenn möglich auf den RMI overhead verzichten.

Soweit verständlich? Falls ja: Dringende Kommentare angebracht?


Nun mein Problem:
Es wäre gut, wenn zwischen beiden Varianten erst beim Start und nicht bei der Installation entschieden werden könnte, oder nach dem Start in einer my.client.Init() Methode. Das my.client package sollte aber ansonsten möglichst unverändert bleiben.

Mein Verdacht:
- unterschiedlicher Code sollte (unbedingt?) unterschiedliche package Namen haben ?
- Das my.basepack Interface sollte durch eine Weiche ("SwitchWrapper") implementiert werden, die entweder my.direct.basepack oder my.remote.basepack aufruft ...

Meine Fragen:
1) geht es auch einfacher, eleganter, als durch den "SwitchWrapper" ?
2) bin ich auf einem Holzweg, sind zwei verschiedene jar Dateien der eindeutig bessere Weg ?
3) falls 1) und 2) ja: wie kann ein client eine von mehreren Bibliotheken (mit gleichen Objekten) gezielt laden ?

4) Any other comment ?
 

mvitz

Top Contributor
Nur nochmal zum besseren Verständnis:

Du hast z.B. eine Klasse
my.basepack.DoSomething
Java:
public class DoSomething {
    public void execute() {...}
}

und eine Klasse
my.client.UseDoSomething
Java:
public class UseDoSomething {
    public static void main(String[] args) {
        ...
        DoSomething doSomething = ...;
        doSomething.execute();
        ...
    }
}

Jetzt soll DoSomething wenn der Client auf Windows läuft direkt JNI verwenden, und wenn nicht, dann per RMI mit einem Server (der dann auf Windows läuft) kommunizieren?

Wenn das der Fall ist, dann macht man das idr so:
Interface: my.basepack.DoSomething
Java:
public interface DoSomething {
    void execute();
}
Klasse: my.basepack.impl.JNIDoSomething
Java:
public class JNIDoSomething implements DoSomething {
    public void execute() {
        // use JNI do do something
    }
}
Klasse: my.basepack.impl.RMIDoSomething
Java:
public class RMIDoSomething implements DoSomething {
    public void execute() {
        // use RMI do do something
    }
}
Klasse: my.basepack.DoSomethingFactory
Java:
public final class DoSomethingFactory {
    private DoSomethingFactory() {}
    public static DoSomething getInstance() {
        if (isWindows) return new JNIDoSomething();
        return RMIDoSomething();
    }
}

Dein Client sähe dann so aus:
Klasse: my.client.UseDoSomething
Java:
public class UseDoSomething {
    public static void main(String[] args) {
        ...
        DoSomething doSomething = DoSomethingFactory.getInstance();
        doSomething.execute();
        ...
    }
}

Edit:
Wenn du dann doch verschiedene Dateien für Windows/andere OS machst, dann kannst du dir die Factory sparen und z.B. die passende Implementierung für das Interface mit dem Java ServiceLoader holen ServiceLoader (Java Platform SE 6)
 

datafiddler

Mitglied
Ja, mvitz, das ist sehr hilfreich. Danke.
Der Ansatz mit einer Factory statt direkt den c'tor aufzurufen ist schon die richtige Richtung, schätze ich.

ClassLoader "Tricksereien" waren mit bisher zu kompliziert,aber während der Formulierung meiner Frage 3) kam mir der Verdacht, dass ich da mal schauen sollte...
ServiceLoader kenn ich auch (noch) nicht, sollte ich mir aber wohl auch ansehen, danke für den Link ;)

-----------------------
Können wir den Thread hier lassen, oder gehört er ins Anfänger-forum ? :oops:
 
Zuletzt bearbeitet:

mvitz

Top Contributor
Im Endeffekt erspart dir der ServiceLoader Tricksereien mit eigenen Classloadern indem er dir eben "registrierte" Implementierungen für ein Interface direkt gibt. Im Endeffekt ist es eben die Frage, was bei dir praktischer/einfacher ist.

Zur Laufzeit unterscheiden, auf welchem OS der Code gerade ausgeführt wird oder ein Win und ein Generic Package zu schnüren und der Nutzer lädt dann das richtige package runter. Für Fall 1) eben eine Factory bauen, die zwischen den OSen unterscheidet und die passende Implementierung zurück gibt, für Fall 2 würde ich den ServiceLoader Mechanismus nutzen.
 

datafiddler

Mitglied
Im Endeffekt ... ist es eben die Frage, was praktischer/einfacher ist.

...ein Win und ein Generic Package zu schnüren und der Nutzer lädt dann das richtige package runter...
... ist mein derzeitiger Stand

... eben eine Factory bauen, die zwischen den OSen unterscheidet und die passende Implementierung zurück gibt

... müsste auch anders gesteuert werden können, so dass ich auch die RMI Variante auf Windows testen kann.

Auch: Zwar ist ein jar file für alle Fälle viel einfacher als zwei, aber der zugehörige windows rmi server mit jni dll will auch richtig installiert sein.

Auf jeden Fall erstmal unter dem "offiziellen Namen" nur das gemeinsame Interface definieren, und die Implementierungen separieren !


Danke nochmals für die schnellen Tips.
 

datafiddler

Mitglied
... ist mein derzeitiger Stand
Auf jeden Fall erstmal unter dem "offiziellen Namen" nur das gemeinsame Interface definieren, und die Implementierungen separieren !
Bei näherer Betrachtung habe ich da Schwierigkeiten. (sollte vielleicht doch ins AnfängerForum ?)

Also: ich habe ein Interface
Java:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface MyClass extends Remote {
  public int myMethod() throws RemoteException ;
}
... dessen Implementierung auf dem RMI Server läuft und, wenn ich ein Remote Objekt über lookup habe, auch von einem Client verwendet werden kann.

Nun will ich eine ähnliche Implementierung auch lokal auf dem Client haben.

Das gemeinsame Interface wäre:
Java:
public interface MyClass {
  public int myMethod() ;
}

und das RMI Interface:
Java:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RMyClass extends Remote, MyClass {
  @Override
  public int myMethod() throws RemoteException;
}

Nun meckert Eclipse, dass entweder die Basis myMethod als "throws RemoteException" deklariert werden soll oder dieser Vermerk im Interface RMyClass entfernt werden muss ???

Aber geht dann ( ohne throws RemoteException ) überhaupt ein als RMyClass implementiertes Object
Java:
  MyClass mightbeRemote = getItSomehow();
  int result = mightbeRemote.myMethod();

???

oder muss bereits MyClass.myMethod als "throws RemoteException;" deklariert werden, obwohl direkte Implementierungen überhaupt nichts von RemoteException wissen

???
 

mvitz

Top Contributor
Das ist das Problem, das RMI Methoden immer diese doofe Exception werfen müssen. Aus diesem Grunde müsste man da vermutlich folgenden Ansatz nehmen:

Dein "wirkliches" Interface
Java:
public interface DoSomething {
    int doSomething();
}

Das "RMI" Interface
Java:
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface DoSomethingOverRMI extends Remote {
    int doSomething() throws RemoteException;
}

Dann brauchst du für den RMI Dienst ja noch die implementierende Server und Client Klassen:
Client:
Java:
public final class RMIDoSomething implements DoSomething {
    @Override
    public int doSomething() {
        try {
            // look up RMI classes
            return rmiInterface.doSomething(); //rmiInterface is of type DoSomethingOverRMI
        } catch (RemoteException ex) {
            throw new RuntimeException("Exception talking with RMI.", ex);
        }
    }
}

Und die RMI Server Variante
Java:
public final class DoSomethingRmiServer implements DoSomethingOverRMI {
    @Override
    public int doSomething() throws Exception {
        DoSomething d = new JNDIDoSomething();
        return d.doSomething();
    }
}
 

datafiddler

Mitglied
Ein Interface wie dein DoSomethingOverRMI wird in jedem Fall gebraucht, es muss gar nicht
Code:
 extends DoSomething
sein.

Allerdings ersetzt dies die RMIException durch eine RuntimeException.

Ein Client, der

DoSomething myObj = getItSomeHow();
myObj.doSomething();

aufruft, muss in jedem Fall damit rechnen, dass eine Exception zuschlägt.
Im lokalen Fall tritt es halt nicht so häufig auf (oder kommt direkt aus dem Native Code) ;)

Code:
throws RemoteException
im interface DoSomething zu deklarieren, schadet andererseits auch nicht.

Dadurch würde auf der Client Seite die Klasse RMIDoSomething entfallen. myObj.doSomething() wäre dann bereits Remote.


Danke für dein Feedback und die Anregung.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
H JavaFX Warnung in package Zeile Allgemeine Java-Themen 2
jumichel Eclipse The package javax.mail is not accessible Allgemeine Java-Themen 3
M Mehrere Ressourcen in einem package ablegen Allgemeine Java-Themen 1
G Mac Package auslesen Allgemeine Java-Themen 17
F Reason: Missing Constraint: Import-Package: okhttp3.internal.http; version="0.0.0" Allgemeine Java-Themen 0
Tommy135 Input/Output Application aus Java package starten Allgemeine Java-Themen 2
J File in Package erstellen & lesen mit Programmstart in externe Projekt Allgemeine Java-Themen 3
B Maven Keycloak library wirft exceptions nach maven package Allgemeine Java-Themen 1
ReinerCoder auf Klassen innerhalb eines package zugreifen Allgemeine Java-Themen 22
T Plötzlich wird package nicht mehr gefunden Allgemeine Java-Themen 3
I Fehler beim Ant-Package erstellen mit Java 9 Allgemeine Java-Themen 1
K Classpath Alle Classen aus einem Package lesen Allgemeine Java-Themen 7
Sin137 Struktur der Klassen & Package Allgemeine Java-Themen 2
F Problem mit "package" Allgemeine Java-Themen 7
L Stack overflow bei einer endrekursiven Funktion (Anwendung: Spezialform des Package Merge) Allgemeine Java-Themen 4
D Classloader ohne Package Allgemeine Java-Themen 10
T Package durchsuchen Allgemeine Java-Themen 11
S leeres package obwohl inhalt da Allgemeine Java-Themen 53
S leeres Package nach neuinstallation des Pc Allgemeine Java-Themen 6
J Suche: Tool zum Auffinden gleichnamiger Klassen (Name und Package gleich) in unteschiedlichen JARs Allgemeine Java-Themen 5
G Gleiche Packages in verschiedenen JAR Dateien - Welches Package wird verwendet? Allgemeine Java-Themen 5
G log4j package filter Allgemeine Java-Themen 10
M Klasse aus xyz.class Datei laden / package entfernen? Allgemeine Java-Themen 4
Bastifantasti Package installieren Allgemeine Java-Themen 2
G Package / Architektur Allgemeine Java-Themen 11
J package javax.servlet does not exist Allgemeine Java-Themen 5
M Dateien aus dem Package im Jar-File rauskopieren Allgemeine Java-Themen 3
V Zugriff auf Default-Package? Allgemeine Java-Themen 6
S Package in verschiedene Projekten einbinden? Allgemeine Java-Themen 3
J Kein Zugriff auf Klassen im Default Package Allgemeine Java-Themen 8
B J-Unit Tests. Alle Tests eines Package einsammen. Allgemeine Java-Themen 4
ARadauer Package Struktur Allgemeine Java-Themen 3
G bild in package Allgemeine Java-Themen 6
G Klasse aus Package auslesen Allgemeine Java-Themen 13
V Alle Klassen eines Package auflisten? Allgemeine Java-Themen 6
G jfreechart probleme mit dem package? Allgemeine Java-Themen 2
E (einfaches) Problem mit import und package (export) Allgemeine Java-Themen 4
E Was ist "default package" in Eclipse konkret? Allgemeine Java-Themen 12
M diff package? Allgemeine Java-Themen 7
T auf Klasse in Default package zugreifen Allgemeine Java-Themen 10
G externe package Allgemeine Java-Themen 7
A Package Probleme Allgemeine Java-Themen 9
J Konstruktor-Aufruf nur aus einem bestimmten Package erlauben Allgemeine Java-Themen 5
G Suche gutes Statistik Package Allgemeine Java-Themen 2
W Package via Reflection parsen Allgemeine Java-Themen 4
minzel ActionListener aus Package Allgemeine Java-Themen 24
P alle Klassen in package auflisten Allgemeine Java-Themen 2
M JNI: nach verschieben in package UnsatisfiedLinkError Allgemeine Java-Themen 3
D Laaaange Klassennamen und Package-Pfade. Allgemeine Java-Themen 5
J Einbinden einer protected-Methode aus anderem Package Allgemeine Java-Themen 2
H .java Dateien in anderem Package Allgemeine Java-Themen 8
S javadoc: package problem Allgemeine Java-Themen 3
G package und classpath grundsatzfrage Allgemeine Java-Themen 7
N Reflection: An Package einer .class-Datei kommen Allgemeine Java-Themen 2
T Problem: Ein Package für 2 Projekte? Allgemeine Java-Themen 3
S Problem bei Umstellung von (default package) auf Packages Allgemeine Java-Themen 10
H Package name aus Class-File auslesen Allgemeine Java-Themen 11
G Java Package Allgemeine Java-Themen 2
EagleEye klassen package problem Allgemeine Java-Themen 3
C Jakarta commons package downloaden und installieren Allgemeine Java-Themen 7
L Package und Klassenname von aufrufender Klasse holen Allgemeine Java-Themen 2
Z auf static Methode aus anderen Package zugreifen? Allgemeine Java-Themen 7
H Klassen in einem Package ermitteln Allgemeine Java-Themen 6
C Problem mit Package Allgemeine Java-Themen 9

Ähnliche Java Themen

Neue Themen


Oben