Jars nachträglich laden (aus den WEB-INF/lib Ordner)

Status
Nicht offen für weitere Antworten.

SebiB90

Top Contributor
Hi,

ich habe folgendes Szenario. Ich habe eine Webanwendung bei der ich eine Libary benutze, die sich beim Starten der Anwendung selbst entpackt und auch weitere Jar Dateien in den WEB-INF/lib Ordner extrahiert, die es brauch. Das Problem ist, dass Tomcat nur beim Starten der Anwendung die Libs aus den WEB-INF/lib Ordner lädt. Die nachträglich extrahierten Libs werden nicht benutzt und daher kommt es zu Exceptions.

Daher frage ich mich jetzt, wie kann ich diese Jars nachträglich laden? Einen neuen URLClassloader erstellen hilft nicht so richtig. Weil ich nicht selbst die Classdateien dann per Reflexion laden will, die Klassen sollen einfach verfügbar seien. So als ob sie bereits beim Start drin gewesen wären. Habt ihr eine Idee, wie man sowas realisieren kann?

Schöne Grüße
Sebi

Nachtrag: Falls es wichtig ist: Die Libary, die sich selbst entpackt, erstelle ich selbst, somit kann ich den Entpackungsprozess beeinflussen und dort die Jars nachladen (Wenn ich wüsste wie).
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
Neuen URL-Classloader mit Webapp-Classloader als Parent erzeugen und dem Thread als Standardclassloader unterschieben.
 

SebiB90

Top Contributor
Also wenn du folgendes meintest:
Java:
ClassLoader parent = Thread.currentThread().getContextClassLoader();
URLClassLoader classLoader = new URLClassLoader(jarUrls, parent);
Thread.currentThread().setContextClassLoader(classLoader);
Dann funktioniert es leider nicht =/
 

SebiB90

Top Contributor
Funktioniert leider so nicht. Komme zu folgender Exception:

Code:
21.10.2009 22:36:09 org.apache.catalina.core.ApplicationContext log
SCHWERWIEGEND: StandardWrapper.Throwable
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
	at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
	at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
	at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4149)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4458)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:722)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:583)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
21.10.2009 22:36:09 org.apache.catalina.core.StandardContext loadOnStartup
SCHWERWIEGEND: Servlet /abcde-standalone threw load() exception
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
	at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
	at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
	at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4149)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4458)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:722)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:583)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

Diese dürfte aber eigentlich nicht kommen, wenn alle jars im ClassLoader drin sind. Bei einem zweiten Start der WebApplikation läuft alles Problemlos, weil dann die ganzen Jars schon entpackt sind und sofort im Classpath drin sind... =/ Aber es muss doch irgendwie beim ersten mal klappen.
 

SebiB90

Top Contributor
Weil wir gerne unser ganzes Programm in einer einzigen Jar Datei weitergeben wollen ohne an die 100 externe Jar Libs mitzugeben. Alle Jars entpacken und zu einer einzigen Datei packen, klappt leider nicht. Da es in den verschiedenen Jars in den META-INF Ordnern Dateien mit gleichen Dateinamen gibt und diese sich gegenseitig überschreiben würden. Ein Beispiel sind die faces-config.xml Dateien. Aber gibt noch weitere.
 
M

maki

Gast
Weil wir gerne unser ganzes Programm in einer einzigen Jar Datei weitergeben wollen
Das ist doch die war :)

ohne an die 100 externe Jar Libs mitzugeben.
was soll denn das bringen? Wie du siehst, versuchst du sie nun doch wieder zu entpacken...

Da es in den verschiedenen Jars in den META-INF Ordnern Dateien mit gleichen Dateinamen gibt und diese sich gegenseitig überschreiben würden. Ein Beispiel sind die faces-config.xml Dateien. Aber gibt noch weitere.
Wieso gibt es denn "überlappende" Dateien?
Schon mal an ein Buildsystem gedacht?
zB. Maven2
 

SebiB90

Top Contributor
Das ist alles bischen komplizierter. Die jar ist nur ein framework für ein Portal, das dann noch erweitert wird, durch die Sachen in dem Webprojekt, in dem dieses framework verwendet wird.
Dieses framework verwendet an die 100 externe jars. Damit wir das framework aber in einer jar weitergeben können, müssen wir diese jars mit packen und später entpacken.

Die einfachere Lösung wäre: alle jars entpacken, neue jar mit dem entpackten zeug und unserem zeug zusammen packen. Aber das geht NICHT, aus folgenden grund: Wir haben unter anderem org.springframework.faces-2.0.8.RELEASE.jar und com.springsource.com.sun.facelets-1.1.14.jar als Libs eingebunden. Beide haben im META-INF Ordner eine faces-config.xml. Diese würden sich überschreiben, wenn wir alles in einer jar packen wollten. Versteht ihr das Problem? (ja ich weiß, man kann mehrere faces config in der web.xml angeben, aber das ist nur ein Beispiel von mehreren Dateien, die 'doppelt' vorkommen)
 
M

maki

Gast
Aber das geht NICHT, aus folgenden grund: Wir haben unter anderem org.springframework.faces-2.0.8.RELEASE.jar und com.springsource.com.sun.facelets-1.1.14.jar als Libs eingebunden.
Ihr wollt da OSGi Bundles als normale Jars verwenden, sonst wären die faces-config.xml Dateien gar nicht sichbar.

Könnt ihr denn nicht die orig. Referenzimplmentierung von Sun verwenden?

So groß wie sich das anhört wäre ein autom. Build nicht verkehrt.
 

heizer_28

Mitglied
vielleicht es ist noch für jemanden interesant ich habe es wie folgt gelöst
interface erstellt dann gelladen und über Interface darauf zugegrifen

Laden :
Java:
ClassLoader parent = Thread.currentThread().getContextClassLoader();
			URLClassLoader urlcl = new URLClassLoader(
					new URL[] { strPathTGoJarFile },parent);

			String strPackage = "packagename.Test ";// Package/Class-Name
			Object instance = null;
			try {
				instance = Class.forName(strPackage, true, urlcl).newInstance(); // call																	// constructor
			} catch (NoClassDefFoundError e) {
				e.printStackTrace();
			}

Interface
Java:
public interface Itest {
	public String getName();
}

classe selbts
Java:
public class Test implements Itest{
	
	
	

	public String getFormatName() {
		return "test";
	}
}


benutzung :
Java:
Itest formO = (Itest) instance ;


Bemerkung : Itest(Interface) befindet sich im externen Jar der sich in WEB-INF\lib befindet, damit es bei der Applikation und dynamisch geladenen Jar bekannt ist
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben