# connectionstatus prüfen



## Stradi (10. Jul 2006)

hallo,

ich benötige einen Thread, der mir in regelmäßigen abständen schaut, ob eine Datenbank für einen anderen Thread erreichbar ist und ein entsprechendes flag setzt! Leider weiß ich aber jetzt nicht, wie ich in JAVA performant und vernünftig programmiert erfahre, ob ich auf eine Datenbank "hinkomme" (konkret: ob ich inserts darauf ausführen kann) oder nicht... ich bräuchte also so eine art "ping-methode" für eine datenbankverbindung... gibts sowas in der richtung, oder gibts konstruktieve vorschläge wie man das anders lösen kann?!

bisher hab ich folgende lösung...:


```
public void run() {
		Connection con = null;
		
		try {
			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		} catch (ClassNotFoundException e) {			
			e.printStackTrace();
		}
		
		for(;;){
			try {				
				if(con!=null&&con.isClosed()){
					//if database is closed, set dbUpFlag = false
					logInst.setDBUpFlag(false);					
					System.out.println(logInst.getDBUpFlag());					
				}else{
					//trying to connect to database
					con = DriverManager.getConnection("jdbc:odbc:SWING_S");
					//on failure ==> catch-block
					//on sucess, set dbUpFlag = true
					logInst.setDBUpFlag(true);					
					System.out.println(logInst.getDBUpFlag());
				}					
				WatchDBThread.sleep(2000);
			} catch (SQLException e) {
				//if an SQLException occures, set dbUpFlag = false
				e.printStackTrace();
				logInst.setDBUpFlag(false);					
				System.out.println(logInst.getDBUpFlag());
			} catch (InterruptedException e) {			
				e.printStackTrace();
			}
		}
	}
```

ich mag diese lösung allerdings nicht, da sie mir ganz und gar nicht schön erscheint... bspw. bin ich mit der con.isClosed() methode ganz und garnicht glücklich. ist diese denn wohl true, wenn der DBServer einfach aus irgend einem grund nicht erreichbar ist.

vielleicht kennt ja jemand eine vernünftigere methode, das zu lösen!

danke schon im voraus für eure gedanken,
stradi


----------



## Stradi (10. Jul 2006)

:shock: 
ach... da seh ich noch was, was ich unbedingt verhindern wollte!!!

ich connecte mich hier ja alle 2 sec auf die datenbank...  :autsch:


----------



## RaoulDuke (10. Jul 2006)

Du könntest in regelmässigen Abständen eine einfache Abfrage laufen lassen, um zu sehen ob die DB noch reagiert. z.B. SELECT now() oder ähnliches. Ich würde nicht darauf vertrauen das die Connection closed meldet wenn die DB nicht mehr erreichbar ist nachdem die Verbindung aufgebaut wurde.


----------



## Guest (10. Jul 2006)

dies führt zu folgender (etwas überarbeiteter) run methode des threads:


```
public void run() {
		Connection con = null;
		
		try {
			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		} catch (ClassNotFoundException e) {			
			e.printStackTrace();
		}
		
		for(;;){
			try {				
				if(con!=null && con.isClosed()){
					//if database is closed, set dbUpFlag = false
					logInst.setDBUpFlag(false);					
					System.out.println(logInst.getDBUpFlag());					
				}else{
					//try to connect to database if con is null
					if(con==null)
					con = DriverManager.getConnection("jdbc:odbc:MyDB");
					//on failure ==> catch-block
					//on sucess, set dbUpFlag = true
					logInst.setDBUpFlag(true);					
					System.out.println(logInst.getDBUpFlag());
				}
				//sleep for two sec.
				WatchDBThread.sleep(2000);
			} catch (SQLException e) {
				//if an SQLException occures, set dbUpFlag = false				
				e.printStackTrace();
				logInst.setDBUpFlag(false);					
				System.out.println(logInst.getDBUpFlag());
				//reinitialize the connection object
				con=null;
			} catch (InterruptedException e) {			
				e.printStackTrace();
			}
		}
	}
```


----------



## Stradi (10. Jul 2006)

@RaoulDuke
hehe... was weiß schon ein sportjournalis - ein bezahlter idiot  ... fear and loathing ist super :lol:
nä, scherz beiseite... danke für deine überlegung
An das mit einer simplen abfrage hab ich auch schon gedacht, nur kommt mir das auch nicht sonderlich performant vor...

ich denke mit der lösung oben könnte das schon soweit richtig funktionieren... im grund ist mir ja sogar fast egal, ob das isClosed checkt ob die DB flöten gegangen ist... wenn das con objekt nicht funktioniert (und das täte es wohl, wenn die DB flöten gegangen wäre) dann kommt sowieso eine SQL Exception, wodurch ich im catchblock con wieder auf null setze und ab dem zeitpunkt eben wieder den connect versuche...

mir gefällt nur die generelle machart meiner lösung nicht so... wirkt irgendwie sehr brachial auf mich... ???:L 

stradi


----------



## RaoulDuke (10. Jul 2006)

Ich habs jetzt nicht ausprobiert, aber laut Doku sieht es sehr so aus das .isClosed() keine Exception wirft wenn die Datenbank nicht erreichbar ist. -> "This Method generally can not be called to determine whether a connection to a database is valid or invalid".

Und gelegentlich aus der Datenbank den aktuellen Timestamp rauszuholen ist nun wirklich nicht sonderlich performancelastig.

Edit:

Hmm, obwohl, vielleicht doch. Hast du das so schon laufen lassen?


----------



## Stradi (10. Jul 2006)

ja schon... nur leider hab ich da eigentlich nur zwei zustände zum testen... da der DB Server, auf den ich mich connecten will noch nicht existiert und ich auf dem rechner nicht die rechte hab, um den odbc treiber für die datenbank zu entfernen (was glaub ich dem flötengehen der db sehr nahe käme...) - da muss sich dringend was ändern 

die zwei zustände sind ganz genau:
datenbank ist die ganze laufzeit erreichbar oder
datenbank ist die ganze laufzeit nicht erreichbar

das führt dazu, dass entweder die con nie geschlossen und nie wieder null wird - weil ja DB immer erreichbar
oder eben, dass con nie gesetzt werden kann, weil DB nie erreichbar! woraus folgt, dass der fehler dann eben nicht beim con.isClosed() auftritt...

aber schreibt man con.isClosed() mal einfach ohne try-catch block schreit der compiler, dass hier ne unhandeled exception vom typ SQLException vorhanden ist! und das klingt mir doch schwer danach, dass im falle einer connection die nicht mehr valide ist die SQLException geworfen wird


----------



## RaoulDuke (10. Jul 2006)

Da gibts je erstmal Unterschiede zu beachten:

Wenn du eine Verbindung zu einer DB aufbaust und die dann runterfährst, dann wird auch der Socket geschlossen und das Connection Objekt merkt vermutlich das die Verbindung geschlossen ist. Wenn die Datenbank auf einem anderen Rechner ist und du das Netzwerkkabel rausziehst, dann wird die Verbindung nicht sauber beendet und dein Programm bemerkt das evtl. garnicht bis du versuchst das nächste SQL Statement abzusetzen.

Das con.isClosed() wirft eine Exception, aber wer weiss schon genau in welchem Fall? Vielleicht liefert es auch einfach ein true wenn deine Datenbank nicht mehr da ist und er gemerkt hat das die Verbindung abgebaut wurde?

In der Doku steht was das die Exception bei Kommunikationsfehlern geworfen wird. Das könnte das sein was du willst, aber sicher bin ich da nicht, sonderlich viel steht da nicht dazu. Also entweder bessere Doku suchen oder ausprobieren. Vielleicht komm ich gleich auch mal dazu das auszuprobieren.


----------



## Stradi (10. Jul 2006)

o.k. - sieht so aus als würde das nicht funktionieren, so wie's ich gemacht habe 

hab das jetzt mal zur laufzeit gemacht, dass ich ihm die DB weggezogen hab... und er hat trotzdem immer noch das flag für "db ist vorhanden" auf true gesetzt...

werd jetzt mal feierabend machen, und morgen da drann weiter rumtüfteln  ...

danke auf jeden fall schon mal für die hilfestellung und die gedanken,
stradi


----------



## Stradi (11. Jul 2006)

also ich hab das jetzt fertig!

der thread wir nun nur noch gestartet, wenn die datenbank nicht da ist, und wieder beendet, sobald die datenbank da ist... im thread benötige ich also nur den connect und einen try catch rundherum... wenns klappt ist die datenbank da und der thread wird beendet, wenns nicht klappt ist die datenbank nicht da, der thread macht mal kurz rauchpause und sieht dann wieder nach, ob die DB da ist!

beim start des threads muss ja die datenbank mal nicht da sein... dazu verwende ich die methode
JDBCConnectionHandler.getConnection(url, usr, pwd);
die der erweiterte JDBCAppender für log4j von danko mannhaupt anbietet... da kommt dann die sqlexception zurück, wenn die datenbank nicht da ist... und der thread wird eben gestartet...

läuft recht fein, das ding...

problem gelöst!

lg,
stradi


----------

