[java] PoolManager

Pagina: 1
Acties:

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Topicstarter
Voor het cachen van connecties naar de database heb ik de volgende classe geschreven, Ik heb alleen het idee dat ik iets vergeet of over het hoofd gezien heb. Iemand een idee wat ik nog toe zou moeten voegen?
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package net.javahova.rdbms;

import java.sql.*;
import java.util.*;
import org.gjt.mm.mysql.*;
/**
 * Title:
 * Description:
 * Copyright:    Copyright (c) 2002
 * Company:
 * @author
 * @version 1.0
 */

public class PoolManager
{
  private int nrConnections = 5;
  private String url = "jdbc:mysql://localhost/javahova";
  private String user = "root";
  private String pass = "";
  private LinkedList freeConnections = new LinkedList();
  private LinkedList takenConnections = new LinkedList();
  private Connection[] myConnections;


  // make it into a singleton sometime
  public PoolManager()
  {
    Class.forName("org.gjt.mm.mysql.Driver").newInstance();

    myConnections = new Connection[nrConnections];
    for (int i = 0; i < nrConnections; i++)
    {
    checkConnection(myConnection[i]);
    freeConnections.add(myConnection[i]);
    }
  }

  private void checkConnection(Connection myConnection) throws Exception
  {
    if (myConnection == null)
    {
    myConnection = DriverManager.getConnection(url, user, pass);
    }
    else if (myConnection.isClosed())
    {
    myConnection = DriverManager.getConnection(url, user, pass);
    }
  }

  public synchronized Connection getConnection() throws Exception
  {
    // get connection from the queue,
    Connection myConnection = (Connection) freeConnections.getFirst();
    // check if the connection is still valid
    checkConnection(myConnection);
    // add connection to taken out
    takenConnections.add(myConnection);
    // log connenction (where is te api ;) )
    // remove connection from free queue
    freeConnections.removeFirst();
    displayInfo();
    return myConnection;
  }

  public synchronized void returnConnection(Connection MyConnection) throws Exception
  {
    takenConnections.remove(myConnection);
    freeConnections.add(myConnection);
    displayInfo();
  }

  private void displayInfo()
  {
    System.out.print("Available connections: " + freeConnections.size());
    System.out.print("Taken connections: " + takenConnections.size());
  }
}

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Topicstarter
a, eerste fout al ontdekt :)
als ik een nieuwe connection aanmaak, moet ik die ook toevoegen aan freeconnections en de oude evt verwijderen :)


Nog eens bekeken, en het was wel goed zo :)

  • Jelmer
  • Registratie: Maart 2000
  • Laatst online: 00:36
Het enige wat ik niet helemaal begrijp is waarom je connections ook in een LinkedList takenConnections zet. Lijkt me overbodig...

Het lijkt mij sowieso handiger om ook te kijken of er nog verbindingen beschikbaar zijn (LinkedList.getFirst() kan een NoSuchElementException gooien). Mocht er geen beschikbaar zijn, dan maak je gewoon een nieuwe. Als die niet meer nodig is return je m, en wordt ie dus aan het freeConnections lijstje toegevoegd. Verder moet je er dan een soort van timertje opzetten zodat als de verbinding niet meer gebruikt wordt, gesloten wordt.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  public synchronized Connection getConnection() throws Exception
  {
    Connection myConnection
    // get connection from the queue,
    try
    {
      myConnection = (Connection) freeConnections.getFirst();
    }
    catch (NoSuchElementException e)
    {
    }

    // check if the connection is still valid 
    // en of we wel een object hebben gekregen,
    // zo niet zorgt deze methode voor een nieuwe verbinding.
    checkConnection(myConnection);
    // log connenction (where is te api ;) )
    // remove connection from free queue
    freeConnections.removeFirst();
    displayInfo();
    return myConnection;
  }

just my 2€cents

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Topicstarter
Op donderdag 31 januari 2002 14:19 schreef Jelmer Barhorst het volgende:
Het enige wat ik niet helemaal begrijp is waarom je connections ook in een LinkedList takenConnections zet. Lijkt me overbodig...

Het lijkt mij sowieso handiger om ook te kijken of er nog verbindingen beschikbaar zijn (LinkedList.getFirst() kan een NoSuchElementException gooien). Mocht er geen beschikbaar zijn, dan maak je gewoon een nieuwe. Als die niet meer nodig is return je m, en wordt ie dus aan het freeConnections lijstje toegevoegd. Verder moet je er dan een soort van timertje opzetten zodat als de verbinding niet meer gebruikt wordt, gesloten wordt.

just my 2€cents
Die noSuchElementException wordt elders in het programma opgevangen en genereerd een #55 ;), verder wil ik vooraf op kunnen geven hoeveel connecties er maximaal gebruikt mogen worden. Dat timertje is in principe wel een idee :),
en die tweede linkedlist weg halen ook wel :)

  • Jelmer
  • Registratie: Maart 2000
  • Laatst online: 00:36
Dan zou ik een eigen exception maken voor de overzichtelijkheid en herbruikbaarheid van je code. Een NoSuchElement bij het vragen van een verbinding vind ik niet netjes. Ik zou dan in mijn Catch een eigen exception gooien: new NoMoreConnectionsException("Connection limmit has been reached");
oid.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Ziet er wel aardig uit (die exception van Jelmer vind ook wel een goed idee trouwens :) ).

Verder kan je het design misschien nog een beetje oppoetsen.... Als ik nu dit post:
code:
1
2
3
4
5
6
7
8
9
10
11
package org.pandoramix.db;

import org.pandoramix.settings.Settings;

import java.sql.Connection;
import java.sql.SQLException;

public interface ConnectionBuilder
{
    public Connection createConnection(JDBCDatabaseType databaseType, Settings settings) throws SQLException;   
}

Weet je waarschijnlijk wel waar ik heen wil ;) .

Je kunt het in dit geval nog beter wat eenvoudiger houden door niet de gegevens mee te geven. De pool wordt dan nog eenvoudiger :+ . Dat is zelfs nog fraaier omdat de pool dan geen kennis heeft van de eigenschappen van de verbinding. Das namelijk niet nodig :) .

Je krijgt dan deze interface, die je meegeeft aan je pool en elders implementeert.
code:
1
2
3
4
public interface ConnectionBuilder
{
    public Connection create() throws SomeException
}

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Topicstarter
mmm, er zat een grove fout in checkConnection() :(
als je een nieuw object aanmaakt dan veranderd de oude reference niet mee... (waar zit ik met mijn kop |:(
nieuwe code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package net.javahova.rdbms;

import java.sql.*;
import java.util.*;
import org.gjt.mm.mysql.*;
/**
 * Title:
 * Description:
 * Copyright:    Copyright (c) 2002
 * Company:
 * @author
 * @version 1.0
 */

public class PoolManager
{
  private int nrConnections = 5;
  private String url = "jdbc:mysql://localhost/javahova";
  private String user = "root";
  private String pass = "";
  private LinkedList freeConnections = new LinkedList();
  private LinkedList takenConnections = new LinkedList();
  private java.sql.Connection[] myConnections;


  // make it into a singleton sometime
  public PoolManager() throws Exception
  {
    Class.forName("org.gjt.mm.mysql.Driver").newInstance();

    myConnections = new java.sql.Connection[nrConnections];
    for (int i = 0; i < nrConnections; i++)
    {
    myConnections[i] = checkConnection(myConnections[i]);
    freeConnections.add(myConnections[i]);
    }
  }

  private java.sql.Connection checkConnection(java.sql.Connection myConnection) throws Exception
  {
    if (myConnection == null)
    {

    return DriverManager.getConnection(url, user, pass);
    }
    else if (myConnection.isClosed())
    {
    return DriverManager.getConnection(url, user, pass);
    }
    else
    {
    return myConnection;
    }
  }

  public synchronized java.sql.Connection getConnection() throws Exception
  {
    // get connection from the queue,
    java.sql.Connection myConnection = (java.sql.Connection) freeConnections.getFirst();
    // check if the connection is still valid
    myConnection = checkConnection(myConnection);
    // add connection to taken out
    takenConnections.add(myConnection);
    // log connenction (where is te api ;) )
    // remove connection from free queue
    freeConnections.removeFirst();
    displayInfo();
    return myConnection;
  }

  public synchronized void returnConnection(java.sql.Connection myConnection) throws Exception
  {
    takenConnections.remove(myConnection);
    freeConnections.add(myConnection);
    displayInfo();
  }

  private void displayInfo()
  {
    System.out.print("Available connections: " + freeConnections.size());
    System.out.print("Taken connections: " + takenConnections.size());
  }
}

(ik heb nog niet alles aangepast..)

Die Exception is wel een goed idee :)

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Topicstarter
martin: comment noted, ik denk er over na :)

  • Tomatrix
  • Registratie: Juni 1999
  • Laatst online: 27-02-2025
Zou je het niet nog generieker kunnen maken:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface Poolable {
   public boolean isFree ();
}

public abstract class PoolableBuilder {
   public abstract Poolable newPoolable ();
   ...
}

public class PoolManager {
   public PoolManager (int size, PoolableBuilder builder) {
    ...;
   }
}

Nu kan je alles poolen wat je maar wilt.

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Ik zeg pak de JDBC extension classes is een groot deel voor je geregeld. Nadeel, je moet een jar file meepackagen.

Wil je het zelf doen, zoals je nu dus al redelijk goed in elkaar hebt zitten: Je hebt waarschijnlijk al een idee hoe je dit geval toe moet passen. En zeer waarschijnlijk ga je een behoorlijk aantal classes gebruiken die dit stukje software van jou moeten benutten. Overweeg dan om er een singleton van te maken. Je wil maar 1 connectie pool kunnen hebben, (neem ik aan) en je wil er makkelijk bij kunnen komen vanuit diverse plekken binnen je applicatie.

Met een singleton doe je twee dingen: Het ding kan maar 1 keer geinstantieerd worden. En je kan er overal binnen jou app makkelijk bij komen.

Wat is een singleton:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class test
{
 static public test instance = 0;

 static public test getInstance
 {
  if (instance == 0)
    instance = new test();

  return instance;
 }

 private test() // private constructor om instantie van buiten deze class onmogelijk te maken.
 {
  // doe hier je nodige initialisatie.
 }
}

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Topicstarter
singleton was ik al van plan:
// make it into a singleton sometime
public PoolManager()
Het gaat trouwens als J2EE app draaien, dus over het distribueren hoef ik niet zo in te zitten :)

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Tomatrix: Zou je het niet nog generieker kunnen maken: Poolable
Yummy :9~

:*

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Mag ik u wijzen op de volgende interfaces:

javax.sql.ConnectionPoolDataSource
javax.sql.PooledConnection
javax.sql.ConnectionEventListener
javax.sql.ConnectionEvent

Onderdeel van de JDBC extensions, die in JDBC 3.0 waarschijnlijk een vast onderdeel van JDBC worden.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: Onderdeel van de JDBC extensions, die in JDBC 3.0 waarschijnlijk een vast onderdeel van JDBC worden.
Ze zitten al standaard in 1.4.0 trouwens... Je driver moet dit dan natuurlijk wel ondersteunen :) .
javax.sql.*: Provides the API for server side data source access and processing from the Java programming language. This package supplements the java.sql package and, as of the version 1.4 release, is included in the Java 2 SDK, Standard Edition. It remains an essential part of the Java 2 SDK, Enterprise Edition (J2EE).

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

Topicstarter
mmm ik hou het nog even bij JDBC 1 :+
Pagina: 1