Možná to někomu pomůže, protože pro mě to funguje docela dobře. Problém lze vyřešit integrací vlastních závislostí. Postupujte podle těchto jednoduchých kroků
Nejprve zkontrolujte chybu, která by měla vypadat takto:
- Provedení metody se nezdařilo:
- java.lang.LinkageError:porušení omezení zavaděče:
- při řešení metody "org.slf4j.impl.StaticLoggerBinder .getLoggerFactory()Lorg/slf4j/ILoggerFactory;"
- zavaděč třídy (instance org/openmrs/module/ModuleClassLoader) aktuální třídy, org/slf4j/LoggerFactory ,
- a zavaděč třídy (instance org/apache/catalina/loader/WebappClassLoader) pro vyřešenou třídu, org/slf4j/impl/StaticLoggerBinder ,
- mají různé objekty třídy pro typ taticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory; použitý v podpisu
-
Podívejte se na dvě zvýrazněné třídy. Vyhledejte je na Googlu jako „StaticLoggerBinder.class jar download“ a „LoggeraFactory.class jar download“. Zobrazí se vám první nebo v některých případech druhý odkaz (stránka je http://www.java2s.com ), což je jedna z verzí jar, kterou jste zahrnuli do svého projektu. Chytře to identifikujete sami, ale my jsme závislí na googlu;)
-
Poté budete znát název souboru jar, v mém případě je to jako slf4j-log4j12-1.5.6.jar &slf4j-api-1.5.8
- Nyní je nejnovější verze tohoto souboru k dispozici zde http://mvnrepository.com/ (ve skutečnosti všechny verze do dnešního dne, toto je stránka, odkud maven získává vaše závislosti).
- Nyní přidejte oba soubory jako závislosti s nejnovější verzí (nebo ponechte obě verze stejné, každá vybraná verze je stará). Následuje závislost, kterou musíte zahrnout do pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
Můžete specifikovat zavaděč třídy? Pokud ne, zkuste zadat zavaděč třídy kontextu takto:
Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(yourClassLoader);
callDom4j();
} finally {
thread.setContextClassLoader(contextClassLoader);
}
Neznám Java Plugin Framework, ale píšu kód pro Eclipse a čas od času se setkávám s podobnými problémy. Nezaručuji, že to opraví, ale pravděpodobně to stojí za pokus.
Zní to jako problém hierarchie classloaderu. Nemohu říci, v jakém typu prostředí je vaše aplikace nasazena, ale někdy se tento problém může vyskytnout ve webovém prostředí – kde aplikační server vytváří hierarchii classloaderů, připomínající něco jako:
javahome/lib - jako root
appserver/lib - jako dítě root
webapp/WEB-INF/lib - jako dítě potomka root
atd
Zavaděče tříd obvykle delegují načítání na svého nadřazeného zavaděče tříd (toto je známé jako „parent-first
"), a pokud tento classloader nemůže najít třídu, pokusí se o to podřízený classloader. Pokud se například třída nasazená jako JAR ve webapp/WEB-INF/lib pokusí načíst třídu, nejprve se zeptá classloader odpovídající appserver/lib k načtení třídy (což zase požádá classloader odpovídající javahome/lib, aby načetl třídu), a pokud toto vyhledávání selže, pak se na WEB-INF/lib hledá shoda s touto třídou.
Ve webovém prostředí můžete narazit na problémy s touto hierarchií. Například jedna chyba/problém, na který jsem narazil dříve, byla, když třída ve WEB-INF/lib závisela na třídě nasazené v appserver/lib, která zase závisela na třídě nasazené ve WEB-INF/lib. To způsobilo selhání, protože zatímco classloadery mohou delegovat na nadřazený classloader, nemohou delegovat zpět strom. Takže WEB-INF/lib classloader by požádal appserver/lib classloader o třídu, appserver/lib classloader by tuto třídu načetl a pokusil se načíst závislou třídu a selhal, protože nemohl najít tuto třídu v appserver/lib nebo javahome /lib.
Takže i když možná nenasazujete svou aplikaci v prostředí webového/aplikačního serveru, moje příliš dlouhé vysvětlení se na vás může vztahovat, pokud má vaše prostředí nastavenou hierarchii classloaderů. To dělá? Dělá JPF nějaké kouzlo classloaderu, aby bylo možné implementovat jeho funkce pluginu?
LinkageError je to, co získáte v klasickém případě, kdy máte třídu C načtenou více než jedním classloaderem a tyto třídy se používají společně ve stejném kódu (ve srovnání, přetypování atd.). Nezáleží na tom, zda se jedná o stejný název třídy nebo dokonce, zda je načtena z identického jara – třída z jednoho classloaderu je vždy považována za jinou třídu, pokud je načtena z jiného classloaderu.
Zpráva (která se za ta léta hodně zlepšila) říká:
Exception in thread "AWT-EventQueue-0" java.lang.LinkageError:
loader constraint violation in interface itable initialization:
when resolving method "org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava/lang/String;)Lorg/w3c/dom/Attr;"
the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader)
of the current class, org/apache/batik/dom/svg/SVGOMDocument,
and the class loader (instance of ) for interface org/w3c/dom/Document
have different Class objects for the type org/w3c/dom/Attr used in the signature
Zde je tedy problém v řešení metody SVGOMDocument.createAttribute(), která používá org.w3c.dom.Attr (součást standardní knihovny DOM). Verze Attr načtená batikováním však byla načtena z jiného classloaderu než instance Attr, kterou předáváte metodě.
Uvidíte, že verze Batik se zdá být načtena z Java pluginu. A ten váš se načítá z " ", což je s největší pravděpodobností jeden z vestavěných zavaděčů JVM (boot classpath, ESOM nebo classpath).
Tři prominentní modely classloaderu jsou:
- delegování (výchozí nastavení v JDK – zeptejte se rodiče, pak mě)
- po delegování (běžné v pluginech, servletech a na místech, kde chcete izolaci – zeptejte se mě, potom rodiče)
- sourozenec (běžné u modelů závislostí, jako je OSGi, Eclipse atd.)
Nevím, jakou strategii delegování používá zavaděč tříd JPF, ale klíčové je, že chcete, aby byla načtena jedna verze knihovny dom a všichni mohli tuto třídu získávat ze stejného umístění. To může znamenat odstranění z cesty ke třídě a načtení jako plugin, nebo zabránění Batiku v načtení nebo něco jiného.