JDBC: Unterschiede Windows und Linux?

Der Held

Erfahrenes Mitglied
Auf die Gefahr hin mich jetzt ganz doll als Java-Trottel zu outen:
Gibt es Unterschiede in der Verwendung von JDBC auf Windows und Linux? Ich weiss natuerlich, dass Java entwickelt wurde um auf allen Plattformen zu laufen, aber:

Ich habe das Problem, dass ich eine Applikation auf einem Windowsrechner habe, die Datenbank auf einer Linuxmaschine. Alles funktioniert. Packe ich die Anwendung auf die gleiche Linuxmaschine wie die Datenbank, kriege ich keinen Zugriff. In den MySQL Logifles steht dann ein Access-Denied Eintrag.

Packe ich die MySQL Datenbank auch auf den Windowsrechner funktioniert es wieder vom (gleichen) Windowsrechener aus, aber nicht vom Linuxrechner. Fehler in der Applikation habe ich ausgeschlossen, da keine Exceptions geworfen werden und da ich an den Logfiles von mysql sehe, dass ja eine Anfrage stattfindet.

Die Privilegien fuer den entsprechenden User liegen alle vor, einmal fuer den Host "%", einmal fuer den FQHN, einmal fuer localhost. In den Logifles steht der Username und Hostname, genau fuer den sind aber ALLE Privilegien angelegt, die Applikation auf dem Windowsrechner verwendet den selben User und da funktionierts. Von der Konsole kann ich mich mit den gleichen Zugangsdaten am MySQL-Client anmelden. Kurz und gut: Die Konfiguration von MySQL scheint fehlerfrei zu sein.

Ich habe zwei Sysadmins in meiner Abteilung gefragt, die sich lange die Datenbank und deren Konfiguration angeguckt haben und irgendwann nur noch Axelzuckend sagten, dass es an der Applikation liegen muss, aber da finde ich einfach keine Fehler, zumal es ja unter Windows problemlos funktioniert und ich sehe, dass die Anfrage an der DB stattfidnet, aber abgewiesen wird. Egal wen ich frage, niemand kann mir sagen woran es liegen kann. Dass die Privilegien richtig gesetzt sind konnte mir der MySQL-Admin auch bestaetigen.

Warum poste ich das hier und nicht im Datenbanken/MySQL-Forum?
Habe ich (http://www.tutorials.de/tutorials230472.html), aber da ich mittlerweile ja keine andere Wahl habe als anzunehmen, dass es mit der Applikation zusammenhaengt denke ich ein Post mit den neu gewonnenen Erkenntnissen in der Java-Ecke ist o.k. Ich hoffe instaendig, mir wird das nicht als Crosspost angekreidet.

Was mich noch stutzig macht, die Applikation (die nicht alleine von mir entwickelt wurde), gibt den String "Database is not available" zurueck, diesen finde ich nirgendwo in den Sourcen, daher gehe ich davon aus, dass das vom Connector/J kommt.

Alles in allem bin ich echt ratlos. Habe jetzt mehrere Tag mit der Fehlersuche zugebracht ohne auf irgendwas zu stossen, habe duztende von Foren und Newsgroups durchsucht, aber was aehnliches hab ich nicht gefunden, immer nur der gleiche Hinweis, der selbst auf der MySQL Seite mit den FAQ zu Access-Denied Problemen zu finden ist:
If you are able to connect using the mysql client, the problem lies with your program, not with the access privileges.

Daher bleibt mir als Letztes anzunehmen, dass es wohl doch einen Unterschied gibt zwischen der Applikation auf Windows und Linux. Kennt irgend jemand einen Parameter, eine Option oder irgendwas, was man beim Connecten mitgeben muss?

Falls jemand den Code sehen will, sagt bescheid, moechte nicht einfach alle Klassen die daran beteiligt sind blind posten, das waere naemlich sehr viel, gleiches gilt fuer die Logfiles (oder zumindest relevante Daten daraus).

Gruss und hoffe auf Antwort,
DH
 
N'Abend,
Der Held hat gesagt.:
Gibt es Unterschiede in der Verwendung von JDBC auf Windows und Linux?
Normalerweise sollte das nicht der Fall sein.
Der Held hat gesagt.:
Was mich noch stutzig macht, die Applikation (die nicht alleine von mir entwickelt wurde), gibt den String "Database is not available" zurueck, diesen finde ich nirgendwo in den Sourcen, daher gehe ich davon aus, dass das vom Connector/J kommt.
Gibts da auch noch ne ausführliche Fehlermeldung? Weil das ist ein bischen mager.
Der Held hat gesagt.:
Kennt irgend jemand einen Parameter, eine Option oder irgendwas, was man beim Connecten mitgeben muss?
Also beim Connect imho nicht. Liest du vielleicht irgendwelchen Parameter aus Dateien oder so ein?
Der Held hat gesagt.:
Falls jemand den Code sehen will, sagt bescheid...
Das wäre nett, äh meine Bescheid. Weil so ins Blaue raten ist unproduktiv.

Gruss
THMD
 
Hallo!

hast du eventuell noch eine Firewall wie ipchains oder sonstiges laufen?
Hast du's schon mal mit einem kleinen Testprogramm (auf dem Linuxrechner) versucht, das nur eine Datenbankverbindung aufbaut und wieder schliesst?
Wie gesagt sieht ganz nach einem Konfigurationsproblem der MySQL DB bzw. der verwendeten Firewall aus.

Gruss Tom
 
Gibts da auch noch ne ausführliche Fehlermeldung? Weil das ist ein bischen mager.
Konnte ich zurueckverfolgen. Ursprung ist eine DatabaseErrorException. Diese scheint aufzutreten weil MySQL die Anfrage abweist. Folgende Zeile taucht dazu im MySQL Logfile auf:
Code:
51210 17:44:53      95 Connect     Access denied for user: 'myuser@server.department.org' (Using password: YES)
Note: User und Hostname aus Sicherheitsgruenden vor Veroeffentlichung geaendert
Also beim Connect imho nicht. Liest du vielleicht irgendwelchen Parameter aus Dateien oder so ein?
Nein. Die Zugangsdaten sind hardcoded in einer eigenen Klasse. Sie werden dann beim erstellen der Connection einfach eingefuegt, kann also nicht daran liegen, dass irgendwelche Ressourcen nicht verfuegbar sind. Auch die Zugangsdaten selbst enthalten keine ungewoehnlichen Zeichen, die zwischen Windows und Linux probleme bereiten koennten.

Hier die Klasse des Connection Pools
Code:
package dbInterface;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import logAndError.*;
import settings.ServerSettings;

/**
 * Singelton class MySQLConnectionPool
 * to connect to the mySQL database
 */
public final class MySQLConnectionPool implements DBConnectionPool {
    private static MySQLConnectionPool connection = null;
    private static int clients;
    private final static int CLIENTS_MAX = 20;
    private Connection dbConnection = null;
    
    /**
	 * Constructor loads the jdbc-driver
	 */
    private MySQLConnectionPool() {
        try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
		} catch (InstantiationException e) {
			ErrorHandling.hardInternal(e.toString());
		} catch (IllegalAccessException e) {
			ErrorHandling.hardInternal(e.toString());
		} catch (ClassNotFoundException e) {
			ErrorHandling.hardInternal(e.toString());
		}
    }
    
    /**
     * Gets a reference to an open db interface back
     * 
     * @return Reference to the db connection
     * @throws SQLException
     * @throws ServerBusyException
     * @throws SQLException
     */
    public static synchronized MySQLConnectionPool getInstance(String name) throws ServerBusyException, DatabaseErrorException {
        if(connection == null) {
            connection = new MySQLConnectionPool();
            
            // Try to connect if it fails, set the connection back to null
            // and throw a DatabaseErrorException
            try {
                connection.connect();
            } catch (SQLException e) {
               connection = null;
               throw new DatabaseErrorException();
            }
        }
        
        // Too many clients are connected
        if(clients >= CLIENTS_MAX) {
            throw new ServerBusyException();
        }
        
        if(connection != null) {
            clients++;
        }
        
        //System.out.println("Connect: " + name + ":" + clients);
        
        return connection;
    }
    
    /* (non-Javadoc)
	 * @see dbInterface.DBConnectionPool#freeInstance(java.lang.String)
	 */
    public synchronized void freeInstance(String name) {     
        clients--; 
        
        if(clients <= 0) {
        	this.close();
        }
        
        //System.out.println("Disconnect: " + name + ":" + clients);
    }
    
    /**
	 * Connect to the database
	 * @param host hostname
	 * @param port port of the mySQL database
	 * @param db databasename
	 * @param user database user
	 * @param pwd password
	 * @throws SQLException if the connection aborts
	 */
	private void connect(String host, int port, String db, String user, String pwd) throws SQLException {
		dbConnection = DriverManager.getConnection("jdbc:mysql://"+host+":"+port+"/"+db+"?user="+user+"&password="+pwd);
	}
	
	/**
	 * Connect to the database with stored settings
	 * @throws SQLException if the connection aborts
	 */
	private void connect() throws SQLException {
	    this.connect(ServerSettings.getURL(), ServerSettings.getPort(), ServerSettings.getDatabaseName(), ServerSettings.getUser(), ServerSettings.getPassword());
	}
	
	/**
	 * Closes connection
	 */
	private void close() {
	    if(dbConnection != null) {
            try {
                dbConnection.close();
                connection = null;
            } catch (SQLException e) {
                // Log if so connection failed to close
                ErrorHandling.softInternal(e.toString());
            }
		}
	}
	
	/**
	 * Executes a SELECT statement
	 * 
	 * @param query SQL query e.g. SELECT * FROM foo
	 * @return ResultSet of the SELECT query
	 * @throws SQLException if the SQL query was not vaild
	 */
	protected synchronized ResultSet insertExecute(String query) throws SQLException {
	    System.out.println("REIN");
		ResultSet queryResult = null;
		Statement sqlStatement = null;
	    System.out.println("VOR");
	    sqlStatement = dbConnection.createStatement();
	    System.out.println("NACH");
	    // If the query succeed get the ResultSet
	    if(sqlStatement.execute(query)) {
	        queryResult = sqlStatement.getResultSet();
	    } 
	    System.out.println("RAUS");		
	    return queryResult;
	}
	
	/**
	 * Executes a INSERT/UPDATE or DELETE statement
	 * 
	 * @param query SQL query e.g. DELETE FROM foo where 
	 * @return the number of rows which were affected
	 * @throws Exception
	 * @throws SQLException if the SQL query was not vaild
	 */
	protected synchronized int updateExecute(String query) throws SQLException, Exception  {
	    Statement sqlStatement = null;
	    
	    try {
			sqlStatement = dbConnection.createStatement();
			return sqlStatement.executeUpdate(query);
		}
		finally {
		    sqlStatement.close();
		}
	}
	
	/**
	 * Count the number of rows which are affected by the SQL statement
	 * 
	 * @param query SQL Statement
	 * @return number of rows
	 * @throws SQLException if the SQL query was not vaild
	 */
	protected synchronized int countRows(String query) throws SQLException {
	    int rows = -1;
	    
	    Statement sqlStatement = null;
	    ResultSet queryResult = null;
	    
	    try {
			sqlStatement = dbConnection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE );
	
			if(sqlStatement.execute(query)) {
			    queryResult = sqlStatement.getResultSet();
			    queryResult.last();
				rows = queryResult.getRow();
				queryResult.beforeFirst();
			}
			
			return rows;
	    }
	    finally {
	        queryResult.close();
	        sqlStatement.close();
	    }
	}
	
	/* (non-Javadoc)
	 * @see dbInterface.DBConnectionPool#getStatement()
	 */
	public Statement getStatement(){
		Statement state = null;
		try {
			state = dbConnection.createStatement();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return state;
	}
}
Die Methode connect stellt die Verbindung zur Datenbank her.
Wenn ich mir den String ausgeben lasse, mit dem die Verbindung dann hergestellt wird sieht alles sauber aus:
Code:
jdbc:mysql://server.department.org:3303/dbname?user=myuser&password=passwd
Habe bereits probiert User und Passwort mit einfachen Anfuehrungszeichen zu uebergeben, aber dann gehts auch auf Windows nicht. Was ja auch einleuchtet, schliesslich sind Anfuehrungszeichen ja auch im Passwort erlaubt.
 
@Tom
Das Projekt laeuft in meinem Home-Directory auf einem gemeinschaftlich genutzten Produktionsserver der Abteilung; mit Firewall hab ich nix zu schaffen, hatte den Verdacht allerdings anfangs auch. Die Sysadmins haben mir versichert, dass es daran nicht liegen kann.

Wegen dem Verdacht der Miskonfiguration: Es funktioniert ja weder wenn die App auf die gleiche Maschine zugreift, noch auf eine entfernte. Beide MySQL Datenbanken sind identisch, der Host fuer den Usernamen ist jeweils so gesetzt, dass es von Ueberall, localhost und dem spezifischen Hostnamen gehen soll. Vom Windowsrechenr aus geht es ja ebenfalls.

Bis jetzt schonmal vielen Dank fuer eure schnellen Antworten.
 
Hallo!

Weshalb verwendest du denn noch den Ur-Alten DriverManager? ... MySQL-j-connector kommt doch mit einer java.sql.DataSource Implementierung (MySQLDataSource). Die DataSource baut dann auch die URL so auf, wie der Treiber es verlangt. Den JDBC Treiber brauchst du dann auch nicht explizit zu laden, dass wird von der MySQLDataSource erledigt... einen Connection Pool bringt der der JConnector auch mit... wenns ein Datenbank unabhaengiger DB Connection Pool sein soll, dann verwende doch den DBPool aus den jakarta Commons... sowas baut man heutzutage doch nicht mehr selbst!
Welche MySQL Version wird eigentlich verwendet?
Schau dir deine MySQL Konfiguration mal mit mysqlaccess an;
http://dev.mysql.com/doc/refman/4.1/en/mysqlaccess.html
Hast du den MySQL Server auch so konfiguriert, dass er auf Port 3306 auf Netzwerkverbindungen lauscht, sieht man den Port bei einem netstat -a?

Gruss Tom
 
N'Abend,

also der Quellcode sieht soweit in Ordnung aus (Bis auf die schon angesprochene Verwendung des DriverManagers ;) )
Also jetzt noch mal zusammengefasst:

Win: Applikation + DB -> geht
Win: Applikation + Linux DB -> geht auch
Linux: Applikation + DB -> geht nicht

Probier doch mal in dem Connect nicht den Server sondern localhost anzugeben, wenn du eh auf dem gleichen Rechner bist.

Gruß
THMD
 
Hi Leute, merci fuer die rege Teilnahme an der Diskussion.

Den Connector/J gibts aus historischen Gruenden. Das Projekt an dem ich arbeite ist schon etwas aelter und wurde erst vor einiger Zeit reanimiert. Das komplette Handling der Datenbank soll sobald es mal eine halbwegs stabile Version gibt dann im naechsten Zyklus gegen eine flexiblere Loesung die auch verschiedene DBS unterstuetzt ersetzt werden. Bis dahin muss es damit klappen.

Leider ist das Projekt bisher nur auf Windows-Systemen getestet worden, daher traten die Probleme erst zu Tage als ein Linuxrechner ins Spiel kam.

MySQL laeuft nicht auf Port 3306 sondern auf 3303, das ist allerdings auch alles ok, die Anfragen passieren da wo sie sollen, kommen ueberall an. Nur dass MySQL eben die Authentifizierung verweigert, wenn die Applikation unter Linux laeuft, wenn der Windowsclient anfragt geht es. Verwendet wird MySQL 4.1, die genaue Buildnummer kann ich erst nachher in Erfahrung bringen wenn ich wieder auf Arbeit bin. Habe den Sonntag mit einem Admin zum Debuggen reserviert :mad:

Wir werden den mysqld nachher im Debugmodus laufen lassen und versuchen Schritt fuer Schritt rauszufinden woran es liegt, ich kann dann hoffentlich mehr Informationen liefern. Alles sehr mysterioes.

@THMD: Localhost hab ich natuerlich auch schon probiert, geht.
Und ja, die zusammenfassung stimmt. Ich koennt ja verstehen, dass es Probleme gibt, wenn ich von nem entfernten Rechner versuche auf die DB zuzugreifen und das nicht klappt, aber lokal? Ausserdem klappte es nicht in der Konstellation
Linux: Applikation + Windows: DB, weshalb ich zum ersten mal darueber nachdachte, dass es was mit Windows/Linux Problemen sein koennte und nicht die DB.

Wie gesagt, wir werden nachher mal die DB im Debugmodus durchlaufen lassen und mal gucken, was bei der Authentifizierung nicht klappt. Javaseitig habe ich die Verbindungsdaten geprueft, es geht auf jeden Fall alles korrekt raus, jetzt gucken wir mal was ankommt.
 
Moin,
Der Held hat gesagt.:
@THMD: Localhost hab ich natuerlich auch schon probiert, geht.
Und ja, die zusammenfassung stimmt. Ich koennt ja verstehen, dass es Probleme gibt, wenn ich von nem entfernten Rechner versuche auf die DB zuzugreifen und das nicht klappt, aber lokal? Ausserdem klappte es nicht in der Konstellation
Linux: Applikation + Windows: DB, weshalb ich zum ersten mal darueber nachdachte, dass es was mit Windows/Linux Problemen sein koennte und nicht die DB.
Könnte es sein, dass es irgendwelche seltsamen Konfigurationen in der /etc/host gibt, oder das der Linuxrechner irgendwelche Problem mit seiner DNS-Auflösung hat? Was sagt er denn, wenn er sich selber via ping server.department.org anspricht?
Gruß
THMD
 
O.K. Also zunaechst mal die Gute Nachricht: Es funktioniert endlich.
Leider kann ich nicht sagen was nun in letzter Konsequenz das Problem behoben hat.

Ich habe testweise waehrend wir den mysqld im Debugmodus haben laufen lassen, den Connector/J 3.0 verwendet, dabei fiel auf, dass bei der Bearbeitung der Anfrage in einen anderen Branch gesprungen wird als bei 3.1, letztendlich wurde die Anfrage aber auch abgewiesen.

Wir haben dann mit anderen MySQL Versionen experimentiert und dabei haben die UNIX-Admins irgendwas am System veraendert. Ich habe seit dem weniger Berechtigungen, kann z.B. den MySQL Client nicht mehr selber starten, aber dafuer funktioniert nun auch der Zugriff von der Applikation unter Linux. Ich kann absolut nicht sagen, was nun geandert wurde oder ob eine andere MySQL - Version verwendet wird. Ich setze wieder den Connector/J 3.1 ein.

@THMD:
Beim Ping wird der Name korrekt aufgeloest, Verbindung ist auch schnell genug.
an die /etc/host komm ich nicht ran, zumindest jetzt nicht mehr. Die Admins waren sichtlich genervt von dem Wochenendeinsatz und sagten mir nur noch sie haetten nichts geandert was nicht vorher mit meinem alten Profil haette funktionieren muessen. :confused:

OK, auf jeden Fall bedanke ich mich recht herzlich bei THMD und Thomas Darimont (schon wieder) dafuer, dass ihr euch die Zeit genommen und nicht wie alle anderen das Problem auf die Applikation abgewealzt und es dabei belassen habt.

Gruss,
DH (sichtlich erleichtert)
 
Zurück