2014-09-28 10 views
7

Nachdem ich die Mongo-Dokumentation gelesen habe, die besagt, dass jede MongoClient-Instanz ihr eigenes Pooling handhabt, wie würde ich dann nur eine Instanz für meine gesamte Anwendung verwenden?Verwenden Sie einen einzelnen MongoClient über einen JavaEE-Webservice

Dies scheint, als könnte es ein Szenario für die Verwendung einer Singleton-Bean sein, aber dies scheint, wie es den Zweck der Verbindungspooling besiegen würde. Wenn nur ein Benutzer gleichzeitig auf die Bean zugreifen könnte, die die MongoClient-Instanz enthält, werden mehrere Verbindungen im Pool niemals gleichzeitig verwendet.

Habe ich mein Verständnis von Singletons falsch verstanden, oder ist das wirklich der richtige Weg?

+0

würde es den Zweck der Verbindung Pooling besiegen – ControlAltDel

+0

Verwenden Sie Frühling, um Mongo-Client zu erstellen? – Suvasis

+0

Nein, ich benutze nicht Spring Ich benutze JavaEE, sorry, ich hätte das in die Frage stellen müssen (Ich habe es zu den Tags hinzugefügt und den Titel der Frage aktualisiert) –

Antwort

9

aber dies scheint, wie es den Zweck der Verbindung pooling.If besiegen würde nur ein Benutzer die Bean zuzugreifen wäre in der Lage, die die MongoClient Instanz zu einer Zeit enthält, sicherlich mehrere Verbindungen im Pool würde nie gleichzeitig benutzt werden.

The javadoc sagt:

Der Java MongoDB-Treiber Thread-sicher ist. Wenn Sie z. B. in einer Web- Serverumgebung arbeiten, sollten Sie eine einzige MongoClient-Instanz erstellen, die Sie in jeder Anfrage verwenden können. Das MongoClient-Objekt verwaltet einen internen Pool von Verbindungen zur -Datenbank (Standardgröße für den maximalen Pool von 100). Für jede Anfrage an die DB (find, insert, etc) erhält der Java-Thread eine Verbindung vom Pool , führt den Vorgang aus und gibt die Verbindung frei. Diese bedeutet, dass die verwendete Verbindung (Buchse) jedes Mal anders sein kann.

Also, wenn Sie ein Singleton mit dem Client darin erstellen. Es kann wie im Javadoc erwähnt wiederverwendet werden. Es ist keine Synchronisation erforderlich, da es Thread-sicher ist.

Wie würde ich vorgehen, nur eine Instanz über meine gesamte Anwendung zu haben?

Einer der Implementierungen könnte sein:

public enum ConnectionFactory { 
    CONNECTION; 
    private MongoClient client = null; 

    private ConnectionFactory() { 
     try { 
      client = new MongoClient(); 
     } catch (Exception e) { 
      // Log it. 
     } 
    } 

    public MongoClient getClient() { 
     if (client == null) 
      throw new RuntimeException(); 
     return client; 
    } 
} 

und verwenden Sie den Client wie in der gesamten Anwendung. Connection pooling wird durch die MongoClient wie dokumentiert.

MongoClient client = ConnectionFactory.CONNECTION.getClient(); 

oder verwenden Sie die @singleton Anmerkung:

@Singleton 
public class SingletonA { 

} 

Siehe: http://tomee.apache.org/singleton-example.html

+1

Danke für die Antwort, was wäre der Unterschied zwischen dies tun und die '@ Singleton' Annotation verwenden, um eine Singleton-Bean zu erstellen? Würde es den gleichen Effekt haben? –

+0

@MattWilliams - Der erste ist eine "Implementierung" eines Singleton-Musters und kann sowohl in einer normalen Java-App als auch in einer Java-EE-App verwendet werden. '@ Singleton' abstrahiert die Implementierung von Singleton vom Entwickler. Das zugrundeliegende Framework sorgt also für die Implementierung einer Singleton-Instanz für die Klasse. Habe meine Antwort w.r.thre Kommentare aktualisiert. – BatScream

+0

@BatScrem - Brilliant, danke für das Aufräumen. Also in meiner 'ConnectionFactory' (oder wie auch immer ich es nenne) Klasse, die die Anmerkung verwendet Ich kann nur eine private MongoClient-Variable haben, instanziieren Sie es im Konstruktor und haben einen einfachen Getter. Können dies nur Ein-Linien-Verfahren sein, z.B. im Konstruktor 'client = new MongoClient();' da Annotation und Injizieren den Fall behandelt, in dem Sie den Getter aufrufen könnten, wenn er nicht instanziiert wurde, oder muss ich noch die Ausnahmebehandlung einbeziehen? –

3

Da Sie in einem Java EE-Umgebung sind, ist der beste Weg, dies CDI Hersteller verwenden zu implementieren wäre:

@Stateless 
public class ConnetionFactory { 

    @ApplicationScoped 
    @Produces 
    public MongoClient mongoClient() { 
    return new MongoClient(); 
    } 
} 

Dann in jeder Bohne, die Sie es verwenden möchten:

@Stateless 
public class MyServiceBean { 

    @Inject 
    private MongoClient mongoClient; 
} 
+0

Ich stimme zu, dass dies der Weg in der JavaEE-Umgebung ist. –