Toon posts:

[j2ee] Servlets & Drivers & classloaders

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb al flink wat info doorgespit, maar ik kom er niet echt achter.

De situatie: Voor een J2EE project waar ik aan werk gebruiken we als connection pool die van bitmechanic (com.bitmechanic.sql.ConnectionPoolManager). Deze implementeerd Driver, en ik laad deze in de init functie van een servlet die via load-on-startup in web.xml automatisch geladen wordt.

Opzich werkt dit en ik kan in de code later (bv in beans die vanuit JSPs worden aangeroepen) gewoon een connectie maken.

Als ik echter via DriverManager.getDrivers() alle drivers opvraag, dan krijg ik de connection pool niet terug. Via een debugger (eclipse) zie ik dat de connectionpool wel gewoon tussen de drivers staat in de private drivers vector van DriverManager, maar dat deze geskipped wordt (lang leve het in de source code kunnen kijken! :) ). Dit komt omdat de Class (met hoofdletter dus) van de Driver die de getDrivers functie dmv de huidige classloader laadt, niet overeenkomt met die van de opgeslagen Driver.

Na even verder kijken blijkt dus dat, de Servlet#init functie een andere classloader meekrijgt dan de Servlet#service functie waar mijn JSP naar gecompileerd wordt.

Waar het echte probleem komt kijken is als ik in een andere web application op dezelfde AS ook de connectionpool laad. Namelijk, om een DB connectie aan de pool toe te voegen moet je een alias opgeven. Als 2 web apps op dezelfde server dezelfde alias opgeven (maar verschillende DB connectie parameters), dan wordt de alias van de app die als 2de geladen wordt genegeerd en krijgt deze gewoon de DB van de eerste app.

Daarom wil ik dus die connectionpool via DriverManager.getDrivers opvragen, om te kijken of deze de opgeven alias al kent (ik kan dan een error geven). Door de classloader problematiek kan ik deze driver echter niet terug krijgen van DriverManager.

Weet iemand hoe ik toch bij die driver kan komen?

  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Andere oplossing (een beetje bot, maar kan wel werken :) ): Probeer een database connectie met de gewenste alias aan te maken (voordat je laadt) en als dat lukt dan bestaat die alias al. Je kunt door de juiste try catch constructie ervoor zorgen dat je alleen verder gaat wanneer je de verwachte exception krijgt.

Verwijderd

Topicstarter
bigbeng schreef op vrijdag 04 maart 2005 @ 14:07:
Andere oplossing (een beetje bot, maar kan wel werken :) ): Probeer een database connectie met de gewenste alias aan te maken (voordat je laadt) en als dat lukt dan bestaat die alias al. Je kunt door de juiste try catch constructie ervoor zorgen dat je alleen verder gaat wanneer je de verwachte exception krijgt.
Nou, dat is nog niet eens zo'n gek idee zeg. Beetje bot inderdaad, maar mischien zeker wel werkzaam!

Update:
Aan de andere kant, mischien werkt ook dit niet namelijk:

De getconnection loopt net zo goed de private drivers vector van DriverManager af en controlleerd of de opgeslagen Class overeenkomt met de Class die de huidige classloader terug geeft. Als de desbetreffende Driver + alias nog niet in de web application zelf is gemaakt (maar wel in de vorige), dan zul je ook niet de connectie terug krijgen.

Hoe de connection pool driver dan zelf wel weet dat de alias al bestond weet ik ook niet (en is moeilijk te achterhalen want het is closed source). Ik ga je suggestie zeker wel even proberen, maar als ik naar de source van DriverManager#getConnection kijk dan doet ie precies hetzelfde als getDrivers, dus ik ben bang dat het niet gaat werken.

Om dit stukje code gaat het. Het staat zowel in DriverManager#getDrivers als DriverManager#getConnection

Java:
1
2
3
4
5
6
// If the caller does not have permission to load the driver then 
        // skip it.
        if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
        println("    skipping: " + di);
        continue;
        }

[ Voor 55% gewijzigd door Verwijderd op 04-03-2005 15:38 ]


  • flowerp
  • Registratie: September 2003
  • Laatst online: 04-02 02:01
Hoewel ik geen echte java expert ben, zie ik de volgende mogelijke oplossingen:

1) Gebruik gewoon een andere connection pool. Wat je nu aan het doen bent is om een bug in die closed source software aan het heenwerken. Aangezien het closed source is, is dat duidelijk niet jou taak. Waarom moet je eigenlijk persie die bitmechanic versie gebruiken? Volgens mij gebruikt niemand dat, hoor!?

2) Je kunt via reflection wellicht de DriverManager class runtime hacken en die drivers vector die je ziet gewoon public maken. Op deze manier hack je jezelf gewoon toegang er toe. Via je unit testen verzeker je je ervan dat dit ook zal blijven werken. Aangezien die bitmechanic lui toch nooit meer met een nieuwe versie lijken te komen (als ik eens zo naar hun site kijk), zal dit waarschijnlijk wel standhouden -als- het werkt.

3) Of dit kan, en of het geen andere problemen gaat geven weet ik niet, maar wat je mischien ook kunt doen is vlak voordat je de connectionpool aanmaakt de default system classloader in de thread te installeren. Dat is even gedoe, want deze zal zo zonder meer niet je connection pool .jar herkennen (daar is juist de classloader van de AS voor). Ook weet ik niet of het nog andere problemen gaat geven dat alle web applications op je AS dezelfde class loader voor je driver gebruiken (de static data van deze driver is dan namelijk automatisch shared tussen je web apps, ik weet niet of dat kwaad kan).

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.