Wie Schreibe ich ein Java-EE/EJB Singleton?
Einen Tag vor meiner Bewerbung war mit einem OHR, mit einem KRIEG, einem EJB-JAR und ein paar Dienstprogramm JAR-Dateien. Ich hatte ein POJO-singleton-Klasse, in einem der utility-Dateien, es funktionierte, und alles war gut mit der Welt:
EAR
|--- WAR
|--- EJB JAR
|--- Util 1 JAR
|--- Util 2 JAR
|--- etc.
Dann habe ich mir eine zweite KRIEG und fand heraus (auf die harte Weise), dass jeder KRIEG hat seine eigenen Klassenlader, so dass jeder KRIEG sieht anders singleton, und Dinge brechen von dort aus. Das ist nicht so gut.
EAR
|--- WAR 1
|--- WAR 2
|--- EJB JAR
|--- Util 1 JAR
|--- Util 2 JAR
|--- etc.
So, ich bin auf der Suche nach einem Weg, um erstellen Sie eine Java-singleton-Objekt, das funktioniert über Kriege (über Classloadern?). Die @Singleton
EJB-annotation schien Recht vielversprechend, bis ich herausfand, dass JBoss 5.1 scheint nicht zur Unterstützung der annotation (die Hinzugefügt wurde, die als Teil der EJB-3.1). Hab ich da was verpasst - kann ich @Singleton
mit JBoss 5.1-Software? Ein Upgrade auf JBoss AS 6 ist keine option jetzt.
Abwechselnd, ich wäre nur so glücklich, nicht zu verwenden EJB implementieren meinem singleton. Was kann ich sonst noch tun um dieses problem zu lösen? Im Grunde brauche ich einen semi-Anwendung-breit* Haken in eine ganze Reihe von anderen Objekten, wie die verschiedenen Cache-Daten-und app-config-info. Als letzten Ausweg habe ich bereits als Verschmelzung meiner beiden Kriege in einem, aber das wäre ziemlich höllisch.
*Bedeutung: verfügbar im Grunde überall oberhalb einer bestimmten Ebene, für die nun größtenteils in meinen WARs - the View und Controller (in einem weiteren Sinne).
Edit: sollte ich wirklich anrufen, es Java EE anstatt J2EE, sollte ich nicht?
Edit 2: Vielen Dank nochmal an @Yishai für all die Hilfe. Nach einigen trial-and-error-es sieht aus wie ich habe herausgefunden, wie die Verwendung eines einzigen ClassLoader über Kriege unter JBoss 5. Ich bin in die Details unten für meinen eigenen Willen, und hoffentlich auch andere das nützlich finden, wie gut.
N. B. dies ist anders, dies zu tun unter JBoss 4 (siehe Yishai Antwort oder meine links unten).
Statt zu schreiben eine jboss-web.xml
für jeden KRIEG, und ein jboss.xml
für Ohr-EJB-JAR, setzen Sie einen jboss-classloading.xml
- Datei in jedem KRIEG, in der gleichen Position wie der DD (web.xml
). Der Inhalt jboss-classloading.xml
werden sollte:
<?xml version="1.0" encoding="UTF-8"?>
<classloading
xmlns="urn:jboss:classloading:1.0"
name="mywar.war"
domain="DefaultDomain"
parent-domain="Ignored"
export-all="NON_EMPTY"
import-all="true">
</classloading>
Dies folgt aus der JBoss-CW hier, während das, was (glaube ich) arbeitet für JBoss 4.x ist beschrieben hier. Mehr Allgemeine Infos auf JBoss classload(ing/ers):
Als am besten ich kann sagen, die JBoss community wiki-docs sind ziemlich fehlt für JBoss 5 im Vergleich zu JBoss 4.
- re: Bearbeiten: Nur wenn Sie Arbeit in der Oracle marketing-Abteilung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Obwohl die EJB3.1 spec führt singleton und Ihre version von JBoss-Software es nicht unterstützt, können Sie mithilfe der JBoss - @Service-annotation zu erstellen, die ein singleton. Anweisungen hier. Auch scheint es, dass Sie JBoss konfiguriert zu isolieren, Ihre ejb-jars und wars von einander. Sie haben nicht zu tun. Sie können sich die loader-repository tag in der jboss-spezifische xml-Dateien, so dass Ihr ganze Ohr teilt sich einen classloader (oder vielleicht, dass zumindest die zwei Kriege teilen sich ein classloader).
Alle, die being said, ich Stimme mit @duffymo, dass eine singleton-die Aktien der Zustand zwischen zwei kriegen ist eine Idee, die Sie sollten gehen, wenn die nicht weglaufen.
Edit: Bezüglich singletons, ich schlage vor, Sie suchen auf Fragen wie diese eine (das hat auch einige schöne balance in die Kommentare).
Die Idee, dass ein Objekt halten zwischengespeicherten Zustand an sich ist ok, vor allem mit EJB3, wo Sie injizieren Ihren Zustand, statt statisch auf Sie verweisen (wenn Sie die @Service-annotation, dann wollen Sie das @ - Hängt JBoss-spezifische annotation). That being said, wenn Sie wurden mit einer "richtigen" singleton hier, dann würde ich erwarten, dass Ihre einzige problem mit der Tatsache, dass Ihre Kriege mit zwei separaten classloadern ist der zusätzliche Speicherbedarf. Ansonsten sind Sie in der problematische Bereich der singletons (wo Sie initialisiert werden, um verwendet werden, alles, was, die Sie verwendet hat, um sicherzustellen, Sie werden erst initialisiert, und natürlich alle code bekommt sehr verbunden mit Ihr wird initialisiert).
Wo Singletons sind wirklich wirklich schlecht ist, wo Sie speichern den Zustand einer Klasse kann den Status ändern und eine andere Klasse abgeholt werden. Es ist im Grunde ein no-no in EJBs bis 3.1, und auch dann macht es eine Menge von parallelitätsproblemen.
Bearbeiten (weitere): du willst Also gehen Sie mit dem classloader-repository. Ich benutze JBoss-4.2.3, so dass ich nicht unbedingt wissen, alle die ins und outs der JBoss5 (die rewrite seine classloader obwohl Sie sagen, es ist fast vollständig rückwärts-kompatibel ist), aber in 4.2.x standardmäßig Ihre Konfiguration verursacht keine Probleme, da alle Ohren auf dem server bereitgestellt wird teilen die selben classloader (der "unified classloader"). Was ich vermute ist, dass die server, die Sie bereitstellen, um die Konfiguration anders, so bin ich nicht sicher, wie Sie Sie zitieren, um mit Ihr zu interagieren, aber was Sie tun müssen ist, fügen Sie eine Datei namens jboss-app.xml im Ohr (in der gleichen Lage wie die application.xml), die wie folgt aussieht:
Ist für JBoss-4.2. 5.1 hat die gleiche Art von tag, hier ist die xsd. Es hat den gleichen loader-repository-Konzept.
Dass sollte es sein. Das heißt, so lange, wie Sie Ihre ejb-jar, war, etc. es nicht haben, dann brauchen Sie nicht es. Jedoch, Ihre Kriege (in jboss-web.xml - dieselbe Lage wie die web.xml), müssen möglicherweise die gleiche Sache. In diesem Fall, solange Sie den Namen des repository-genau die gleiche Art und Weise (wenn ich das richtig verstanden habe - noch nie selber ausprobiert) Sie teilen sich den selben classloader. Das gleiche gilt für die EJB-Konfiguration in der jboss.xml das geht in der gleichen Position wie die ejb.xml.
Diese könnte es ein wenig klarer.
@Service
hat auch seine Kopfschmerzen. Trotzdem, vielen Dank für Ihre Hilfe! Poste ich eine weitere Frage, wenn ich etwas bestimmtes.Ich würde so konfigurieren Sie einen eigenen Objekt pool auf dem app-server, so dass es nur enthalten die einzige Instanz.
Warum würden Sie wollen, dies zu tun ist die eigentliche Frage. Klingt wie alle Ihre apps gekoppelt werden, auf diese Weise. Und Google ist die Beseitigung singleton von seinen apps. Warum sind Sie sehen passen, um es zurück?
Können Sie eine MBean und binden Sie es zu JNDI, dann rufen Sie es, wo immer Sie wollen, es zu benutzen.
Den MBean bereitgestellt werden kann, in einem .sar-Datei
Wenn Sie mit Java EE 6 ist, dann unterstützt es singleton-EJBs.
Wenn möglich, nehmen Sie einfach die Klasse, die das singleton -, legte es in ein GLAS, nehmen Sie das GLAS AUS dem OHR, und fügen Sie die JAR auf dem JBoss-Klassenlader (über den system-classpath, oder ein paar lib-Verzeichnis). Dies stellt der Klasse in einem einzigen classloader, der gemeinsam von beiden WARs.
Singleton nicht in der Lage zu "sehen" alles, was in Ihren Anwendungen zu Kriegen usw., soweit Sie in der unteren classloader.
Aber es gibt nichts stoppen Sie von der Injektion in das singleton (beim server Start) eine Fabrik-Klasse, welche stammt aus dem Kriege, et al, und diese Klasse hat Zugriff auf alle apps-Klassen. Das macht das singleton mehr von einem einfachen container.
Aber dies ist einfach zu tun.
Auch, wenn Sie dies tun, stellen Sie sicher, dass beim Herunterfahren der Anwendung, dass Sie alle Instanzen gehalten, die von dieser singleton befreit werden. Jeder Klasse referenzieren, die von der singleton nicht GC würde, wenn Sie heben Sie die Bereitstellung der Anwendung. Also, wenn Sie einen Verweis auf Ihre app gespeichert in der singleton -, dann wird der server enthält einen Verweis auf das Singleton-classloader, dass classloader enthält einen Verweis auf das singleton-Klasse, die hält Referenz auf Sie apps, die Klasse, die einen Verweis auf das apps-CLASSLOADER, und enthält einen Verweis auf alle Klassen, die in Ihrer app. Keine schöne bescherung hinter sich zu lassen.