# Reflection in JEE6



## JanHH (22. Dez 2012)

Hallo,

überlege, eine JEE6-Webanwendung zu realisieren, bei der es einen Bestandteil gibt, bei dem die Programmlogik während der Laufzeit der Anwendung verändert bzw. erweitert bzw. dynamisch gesteuert werden muss.

Eine Lösung wäre, diesen Teil mittels der Implementierung einer eigenen Skriptsprache zu steuern, machbar aber ziemlich aufwändig, wenn auch sicher langfristig gesehen die beste Lösung.

Andere Überlegung ist, das ich diese Teile direkt als java-Klassen baue (die ein bestimmtes Interface implementieren müssen), die dann während der Laufzeit der Webanwendung per Reflection dynamisch geladen werden.

- ist das machbar oder verstösst das zu arg gegen die JEE6-Spezifikationen?
- kann man Klassen, wenn die enthaltene Logik sich ändert,auch wieder "ent-laden", um sie dann neu vom Classloader laden zu lassen? Oder wird das eh getan, wenn ich sie explizit per Reflection erzeuge? Also das immer das gerade aktuelle class-File geladen wird? Oder muss ich mich da gar mit der Implementierung eines eigenen class loaders rumschlagen?

Gruß+Danke
Jan


----------



## Ullenboom (22. Dez 2012)

Reflection braucht man eigentlich als normaler Entwickler selten -- das ist eher was für Lib-Entwickler, die OR-Mapper schreiben, oder Gui-Binder oder so. Kannst du mehr über dein Problem schildern, vielleicht hilft ja auch das Strategie- oder State-Muster weiter.


----------



## Nogothrim (22. Dez 2012)

Ich glaube Reflection hilft dir bei deinem Vorhaben nicht sehr viel weiter. Wenn du Klassen dynamisch laden willst, hört sich das eher nach OSGI an. Wenn es nur darum geht, Businesslogik zu steuern könnte auch eine Rules-Engine wie JBoss Drools sinnvoll sein, wobei das auch ein Monster ist, was es erstmal zu bändigen gilt


----------



## JanHH (22. Dez 2012)

Ich hab eine Klasse, deren Name und Inhalt erst zur Laufzeit der Anwendung zur Verfügung steht, von der man nur weiss das sie ein bestimmtes interface implementiert. Diese muss ich irgendwie "zu fassen kriegen" in meiner Webanwendung.


----------



## JohannisderKaeufer (22. Dez 2012)

Zu der  Problemstellung fällt mir dann JNDI ein.

Im Application Server wird ein Objekt abgelegt und mit einem Namen versehen.

In der Anwendung wird dann über den Namen per lookup dieses Objekt geladen und dann auf das entsprechende Interface gecastet.


Oder bei neueren Applicationservern CDI Contexts and Dependency Injection ? Wikipedia 

Damit sollte sowas auch umgesetzt werden können.


----------



## Ullenboom (23. Dez 2012)

Na dann reicht doch Class.forName(...). Das ist noch kein Reflection  Wenn die Klasse dann immer eine bestimmte Schnittstelle implementiert, dann ein Cast auf den Typ und Methoden aufrufen.


----------



## JanHH (23. Dez 2012)

Ullenboom..

ja, genau das hatte ich vor. Bin mir nur unsicher ob ich das darf, in einer JEE6-Anwendung.


----------



## Ullenboom (23. Dez 2012)

Ja, das ist erlaubt. Siehe auch http://www.oracle.com/technetwork/java/restrictions-142267.html:



> Why is there a restriction against using the Java Reflection APIs to obtain declared member information that the Java language security rules would not allow? Doesn't Java automatically enforce those rules?
> 
> Contrary to common belief, most of the Java Reflection API can be used from EJB components. For example, loadClass() and invoke() can both be used by enterprise beans. Only certain reflection methods are forbidden.



und



> Why all the restrictions on creating class loaders and redirection of input, output, and error streams?
> 
> Class loading is allowed, but creating custom loaders is not, for security reasons. These restrictions exist because the EJB container has responsibility for class loading and I/O control. Allowing the EJB to perform these functions would interfere with proper operation of the Container, and are a security hazard.


----------



## JanHH (24. Dez 2012)

sehr schön.

kann man eine geladene Klasse auch wieder ausladen, um sie (in aktualisierter Form) neu zu laden, wenn sich das class-File geändert hat?


----------



## Ullenboom (24. Dez 2012)

Das kann nur ein eigener Klassenlader, der aber laut Vorgabe nicht erlaubt ist. Jedoch könnte man mit dem Klassenlader vom Java EE-System rumspielen, der Hot-Deployment-fähig ist. Problem: der könnte produktiv nicht aktiviert sein, denn das das Überwachen vom Datensystem auf Änderungen kostet Performance.


----------



## JanHH (4. Jan 2013)

Ähm.. wenn ich bei einer JEE-Anwendung, die im JBoss läuft, zur Laufzeit ein neues class-File hinzufüge, dann führt das doch eh zu einem hot redeploy, oder? Eher unbrauchbar.. Kann man das neue class-File nutzen, ohne das der Server einen hot deploy durchführt?


----------



## Ullenboom (5. Jan 2013)

Genau das ist hot deployment, wenn der Container Klassen austauscht oder im Betrieb neue hinzufügt. Ist aber ein Server-internal. Selbst kannst du das nicht als Feature für deine eigenen Programme nutzen.


----------



## JanHH (6. Jan 2013)

Aber der tauscht ja nicht einzelne Klassen aus sondern die gesamte Webanwendung..


----------



## Ullenboom (6. Jan 2013)

Er tauscht Klassen aus, in dem er sie mit einen neuen Klassenlader lädt. Der alte Klassenlader mit den alten Klassen wird dann verworfen, was ein Class-unloading ergibt. Neue Klassen bekommt man also im Prinzip nur dann, wenn man alles neu lädt (JRebel und sonstige Tricks jetzt mal außen vor gelassen).


----------



## JanHH (6. Jan 2013)

Hm ok. Ich dachte, er lädt eine komplett neue Instanz der Webanwendung, wobei die bestehenden HTTP-Sessions der alten Version mit dieser weiterlaufen (diese also erst entfernt wird wenn da alle Sessions weg sind), und alle neue zur neue version geleitet werden. Ist das nicht so?


----------



## Ullenboom (7. Jan 2013)

ja ist auch so. der alte klassenlader bleibt noch aktiv solange wie es noch z.b. einen hängenden request gibt. aber neuer request = neue anwendung = neuer klassenlader = neues spiel.


----------



## DerFeivel (7. Jan 2013)

JohannisderKaeufer hat gesagt.:


> Zu der  Problemstellung fällt mir dann JNDI ein.
> 
> Im Application Server wird ein Objekt abgelegt und mit einem Namen versehen.
> 
> In der Anwendung wird dann über den Namen per lookup dieses Objekt geladen und dann auf das entsprechende Interface gecastet.



Klingt für mich nach der "JEE gewolltesten" Lösung für dein Problem. (Mit CDI leider was sowas angeht noch keine Berührungspunkte gehabt).


Du hast dann einmal ein Artefakt, welches das Objekt welches das Interface implementiert beinhaltet und über JNDI registriert. Und einmal deine App, welche das Objekt dann über einen JNDI-Lookup ermittelt.


----------



## fastjack (7. Jan 2013)

overkill, ich würde auch class.forName anvisieren.


----------



## DerFeivel (8. Jan 2013)

fastjack hat gesagt.:


> overkill, ich würde auch class.forName anvisieren.



In der initialen Anfrage ging es doch darum neue Klassen (die noch nicht im deployten Artefakt vorhanden sind) dynamisch nachzuladen. 
Und dann dürfte (ohne es jetzt ausprobiert zu haben) ein class.forName nicht funktionieren, weil die neue Klasse dem Klassloader ja nicht bekannt ist.


----------



## Ullenboom (8. Jan 2013)

Wenn der Klassenlader ein forName() bekommt sucht er die Klasse. Wäre sie schon da, dann würde er sie nicht suchen und neu laden. Daher kann man nicht mehrmals in einer Webandwendung (=ein Klassenlader) die gleiche Klasse laden. Aber immer neu aufgebaute, und in den Suchpfad untergebrachte Klassen nach dem Bauplan

ASDFASAD345345.class, die MyInterface implementiert

im Prinzip schon. Aber auswechseln eben nicht, hier müsste man tricksen.

Eine relativ ordentliche Lösung wäre wohl mit JCA sich die Klassen holen zu lassen.


----------



## FArt (9. Jan 2013)

Ich finde der Ansatz an sich ist so nicht sinnvoll.

Es soll wohl in einer Enterpriseumgebung eine Art Plugin-Mechansimus realisiert werden.

Hier könnte sich OSGI anbieten. 

Sonst hält aber auch ein Applicationserver verschiedene Mechanismen bereit, die ich mir zunutze machen kann, z.B. JNDI, Hot-Deployment und Redeployment. Allein diese Features reichen aus, einen Registry- und Discoverymechanismus zu implementieren. Also im Prinzip wie Reflection in einer normalen Javaumgebung, aber mit Mitteln aus dem EE Umfeld. Vorteil: ich halte mich an die Spec und bin offen für Erweiterungen (z.B. Clustering).


----------

