Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session."

Added by JavaKru09 over 1 year ago

Hallo Alexander,

ich versuche gerade einen brauchbaren Bericht für folgende Exception zusammenzustellen:

Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session.
de.root1.simon.exceptions.SessionException: Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session.
        at de.root1.simon.Dispatcher.checkForInvalidState(Dispatcher.java:655)
        at de.root1.simon.Dispatcher.invokeNameLookup(Dispatcher.java:223)
        at de.root1.simon.NameLookup.lookup(NameLookup.java:69)
        at de.root1.simon.Simon.lookup(Simon.java:189)
        at cardgames.model.maumau.MauMauPlayer.takeASeat(MauMauPlayer.java:170)
        at cardgames.model.maumau.MauMauPlayer.takeASeat(MauMauPlayer.java:159)
        at cardgames.model.maumau.MauMauPlayerTest.testSimonRegister(MauMauPlayerTest.java:199)

Vergeblich versuche ich log4j dazu zu bringen, SIMON's Aktivitäten zu protokollieren. Ich verwende NetBeans 6.9.1 und habe im Projektverzeichnis ein Unterverzeichnis conf, in dem die angehängte log4j-Konfiguration MauMauTable.log4j.properties liegt. Diese wird offenkundig geladen aber in dem TestCase, der den obigen Fehler verursacht, nicht verwendet.

Tatsächlich gibt es neben dem Unterverzeichnis conf das Unterverzeichnis log, in dem ich die Datei table.log erwarte. Diese Datei taucht aber auf der ganzen Festplatte nirgends auf.

Eingebunden wird MauMauTable.log4j.properties in einem TestCase, der in der Klasse MauMauTable eine statische Methode folgender Gestalt abarbeitet:

// LOGGER der Klasse
static Logger LOGGER = Logger.getLogger(MauMauTable.class);
// Methode, die das Konfigurationsfile bearbeitet
public static void setUpLogging(String[] args) {
    BasicConfigurator.configure();
    File f = cardgames.Starter.getLogPropertiesFile(args);
    if (f != null) {
        if (f.exists() && f.canRead())
            // Tests zegen: genau hier wird die Konfigurationsdatei tatsächlich auch verwendet
            PropertyConfigurator.configure(f.getAbsolutePath());
        else
            System.err.println("Failed to configure logging from file " + f.getAbsolutePath());
    }
    else
        LOGGER.setLevel(Level.ERROR);
}

Kannst Du mir mit einem geübten Blick sagen, wie ich die Konfiguration so ändere, dass die Datei table.log entsteht und SIMON's Meldungen dort auflaufen?

Viele Grüße von

Christian

MauMauTable.log4j.properties - abgeleitet von simon_logging.properties (2.9 kB)


Replies (9)

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by achristian over 1 year ago

Woran machst du denn aus dass die LogConfig tatsächlich geladen wird?

Im Prinzip ist es egal ob du die Anwendung "normal laufen lässt" oder einen "junit test" startest. Wichtig ist nur, dass die JVM als Startparameter ein

-Djava.util.logging.config.file=logging.properties

benutzt. Du brauchst nicht zwingend ein "log" und "conf" verzeichnis. Das hängt ganz von deiner Log-Config ab. Wichtig ist in erster Linie nur, dass der Startparameter auf die logconfig file zeigt.

Dann brauchst du auch keine Änderungen im Code.

In den SIMON Tests hab ich das noch über ein manuelles lesen der Property-File gelöst. Wird sich aber in naher Zukunft ändern.

- Alex

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by JavaKru09 over 1 year ago

Hallo Alexander,

das mit dem Logging eines TestCases hat sich vorerst deshalb erledigt, weil der Anlass, die de.root1.simon.exceptions.SessionException: Cannot handle method call "Simon.lookup({... , weggefallen ist. Vermutlich der dümmstmögliche Fehler hatte ich im Zuge des unregisters irgendwo die ganze Simon-Registry angehalten mit

simonRegistry.stop();

Und das sollte man auf jeden Fall lassen, scheint mir. Denn seitdem ich das registrierte Objekt per simonRegistry.unbind(...); abmelde und die Registry nicht stoppe, habe ich die Exception oben nicht wiedergesehen und kann die Frage, wie ich für einen speziellen TestCase eine bestimmte Log-Konfiguration lade, erstmal auf sich beruhen lassen.

Vielen Dank für Deine Antwort(en) sagt

Christian

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by Arne411 about 1 year ago

Ich würde diesen Thread wegen der o.g. Ausnahme gerne noch mal aufgreifen. Beim wiederholten Starten und Stoppen meines Servers erhalte ich nämlich die gleiche Meldung, wenn der Client nicht beendet wird, sondern nur die Session beendet hat. Nun könnte ich ja einfach auf das

SessionVerwaltung.m_registry.stop();

verzichten, aber in der Doku steht es drin und möglicherweise gibt es dafür einen Grund.

Daher also meine 1. Frage
was hat es mit der Exception

Cannot handle method call "Simon.lookup({...}, AdvoluxServer)" on already closed session. isRunning=true isClosing=true

eigentlich auf sich. Immerhin tritt diese Ausnahme Clientseitig auf, obwohl ich mein
lookup.release(server)

auf der Clientseite aufgerufen habe. Beim Schließen und anschließenden Neustart des Clients funktionierts übrigens wieder, so dass ich eher mal eher davon ausgehe, dass noch etwas mehr freigegeben werden muss.

Meine 2. Frage (abhängig von der 1.)

Was muss ich machen, um meinen RemoteClient vollständig zurückzusetzen, damit er (auch nach dem zwischenzeitlichen Stoppen und Starten des Servers) wieder arbeiten kann ?

viele Grüße
Arne

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by achristian about 1 year ago

Hallo Arne,

Ein Registry#stop() solltest du erst aufrufen, wenn du den Server komplett beenden willst. Dadurch wird der ServerSocket beendet und alles was in der Registry gebunden ist entfernt. Alle noch offenen Netzwerkverbindungen werden gekappt.

Wenn ein Client eine Verbindung zum Server aufnimmt (ausgelöst durch ein lookup), dann wird eine Socketverbindung hergestellt. Diese Verbindung wird über eine Session verwaltet. Solange die Netzwerkverbindung intakt ist, ist die Session gültig.

Beendest du den Server, den Client oder trennst du die Netzwerkverbindung, wird die Socketverbindung getrennt und somit die Session geschlossen. Wenn du nun versuchst eine Methode über's Netzwerk aufzurufen (egal in welche Richtung), dann bekommst du die von dir zuletzt genannte Fehlermeldung.

Ist eine Session erstmal geschlossen, kannst du sie nicht mehr wiederbeleben. Du musst erneut einen Lookup auf das RemoteObjekt machen.

Kurzum: Die Netzwerkkommunikation mit SIMON ist zustandsbehaftet. Man kann nicht nach belieben Server oder Clients während einer bestehenden Netzwerkverbindung beenden, und nach erneutem Starten so weitermachen als wäre nichts geschehen.

Falls genau das dein problempunkt ist, hoffe ich dass ich das ganze ausreichend erklärt habe. Wenn nicht: Wo hängts noch? Wo müsste ich die Doku/JavaDoc ergänzen verbessern damit es von Anfang an klar ist?

Gruß
Alex

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by Arne411 about 1 year ago

Hallo Alex

ich habe das Problem wohl etwas unklar beschrieben

Zitat : Ist eine Session erstmal geschlossen, kannst du sie nicht mehr wiederbeleben. Du musst erneut einen Lookup auf das RemoteObjekt machen.

Ein neues Lookup wird auch gemacht. Das Problem ist, dass ich - in der einfachen Variante - nur prüfe, ob der Remoteserver überhaupt erreichbar ist. Das geht auch beliebig oft hintereinander, solange der Server nicht zwischendurch beendet wurde. Wurde er zwischendurch beendet, muss ich auch den Client beenden um anschließend ein neues Lookup machen zu können. Ich möchte aber aus der nicht beendeten Client-Anwendung ein neues Lookup machen, das mir dann nicht diese Ausnahme wirft (und in der Folge auch verhindert, dass sich der Client überhaupt anmelden kann).

hier der Source für das Testen, ob der Server erreichbar ist

/**
     * Prüft, ob der Remoteserver erreichbar ist. 
     * @param antwort
     * @return true wenn der remoteserver auf dem Host erreichbar ist
     */
    public static boolean IsRemoteServerAvailable(String host, int port, StringBuffer antwort) {
        boolean erreichbar = false; 
        Lookup lookup = null; 
        IAdvoluxRMIServer server = null; 
        try {
            if (InetAddress.getByName(host).isReachable(1500) == true) {
                lookup = Simon.createNameLookup(host, port);
                lookup.lookup(IAdvoluxRMIServer.BIND_ADVOLUX_SERVER);
                server = (IAdvoluxRMIServer) lookup.lookup(IAdvoluxRMIServer.BIND_ADVOLUX_SERVER);
                lookup.release(server);
                lookup = null; 
                server = null; 
                antwort.append(String.format("Der Advolux-Remote-Server ist erreichbar.",host,port));
                erreichbar = true; 
            }
            else {
                antwort.append(String.format("Der Recher '%s' ist nicht bekannt.",host));
            }
        } catch (UnknownHostException e) {
            antwort.append(String.format("Der Recher '%s' ist nicht bekannt.",host));
        } catch (LookupFailedException e) {
            antwort.append(String.format("Die Verbindung zum Advolux-Remote-Server konnte nicht aufgebaut werden. Möglicherweise sind die Advolux-Versionen nicht identisch."));
        } catch (EstablishConnectionFailed e) {
            antwort.append(String.format("Der Advolux-Remote-Server wurde nicht gefunden und ist möglicherweise nicht gestartet oder wird durch eine Firewall blockiert.",host,port));
        } catch (IOException e) {
            antwort.append(String.format("Der Recher '%s' ist nicht bekannt.",host));
        } catch (Exception e) {
            antwort.append(e.getLocalizedMessage());
            LogHelper.LogError(e.getLocalizedMessage());
        }
        finally {
            try {
                if ( (lookup != null) && (server != null) ) {
                    lookup.release(server);
                }
            } catch (Exception e) {
                LogHelper.LogError(e.getLocalizedMessage());
            }
        }
        return erreichbar; 
    }.

Ich will also nicht einfach weitermachen, sondern völlig neu aufsetzen. Leider ist mir das (nach dem Beenden des Servers, während der Client weiterläuft) nur möglich wenn ich auch den Client beende. Oder (und das war meine zweite Frage) muss ich außer dem Release (und einem erneuten Lookup) noch etwas anderes beachten, weil irgendeine Art von Zustand noch nicht zurückgesetzt wurde ?

viele Grüße
Arne

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by Arne411 about 1 year ago

Ok beim nachträglichen drüberschauen ist mir folgendes aufgefallen

     lookup.lookup(IAdvoluxRMIServer.BIND_ADVOLUX_SERVER);
     server = (IAdvoluxRMIServer) lookup.lookup(IAdvoluxRMIServer.BIND_ADVOLUX_SERVER);

Das scheint mir nicht ganz richtig zu sein ;-) ich probiere mal ob der Fehler auch ohne diese unnötige Verdoppelung auftritt

Gruß Arne

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by achristian about 1 year ago

Das würde das Problem erklären. SIMON verwendet zu einem Server immer nur eine Socketverbindung, egal wieviele Remote-Objekte man von diesem Server holt.

In diesem Fall wurden 2 geholt. Davon eines ohne weitere Referenz. Selbst wenn man nun ein Objekt "released", bleibt eines im Nirvana hängen.
SIMON zählt also mit wieviele Objekte man geholt und released hat. Und erst wenn der Zähler bei 0 angekommen ist, wird die Session sauber entfernt und somit die Netzwerkverbindung ordnungsgemäß getrennt.

Muss mal schauen ob ich hier die JavaDoc nicht entsprchend verbessern/erweitern kann, so dass das sofort offensichtlich wird.

- Alex

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by Arne411 about 1 year ago

Also es funktioniert jetzt in jede gewünschte Richtung ..

ich glaube die JavaDoc muss da nicht verbessert werden, war halt ein Flüchtigkeitsfehler von mit :-/

vielen Dank u. viele Grüße
Arne

RE: Log4J-Frage für einen Fehlerbericht zu "Cannot handle method call "Simon.lookup({...}, testSimonRegister)" on already closed session." - Added by achristian about 1 year ago

Hab die JavaDoc dennoch ergänzt/verbessert:

*de.​root1.​simon.​Lookup*

public Object lookup(String lookupString) throws LookupFailedException, EstablishConnectionFailed

Tries to lookup a remote object on the server. A successful lookup includes:
* established socket connection to server, if not already connected
* increased reference counter for this client-to-server connection by 1
* return of the requested remote object
To avoid leaks, ensure that remote objects are released after use. For releasing objects, please refer to Lookup.release(java.lang.Object).
*de.​root1.​simon.​Lookup*

public boolean release(Object remoteObject)

Releases are remote object. If provided object is null, method will simply return. Releasing a remote objects leads to:
* release related SIMON resources
* decrease reference counter for this client-to-server connection by 1
* if reference counter reaches 0, the client-to-server connection will be disconnected and cleaned up

(1-9/9)