Хибернация в Glassfish - Ejb3Configuration NoClassDefFoundError

Поставих библиотеките на Hibernate както в домейна Glassfish, така и в колекцията от библиотеки на моя проект в Netbeans. hibernate-entitymanager.jar съдържа както HibernatePersistence (последния клас в стека за извикване), така и Ejb3Configuration, така че съм доста объркан защо получавам грешката за липсващ клас за Ejb3Configuration.

java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.ejb.Ejb3Configuration
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:130)
    at com.sun.enterprise.server.PersistenceUnitLoaderImpl.load(PersistenceUnitLoaderImpl.java:149)
    at com.sun.enterprise.server.PersistenceUnitLoaderImpl.load(PersistenceUnitLoaderImpl.java:84)
...

person Jeff Ferland    schedule 22.05.2009    source източник


Отговори (2)


Никога преди не съм виждал това конкретно съобщение за грешка, но мога да обясня малко какво означава и да дам една възможна причина.

Линията

java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.ejb.Ejb3Configuration

не означава, че JVM не може да намери класа org.hibernate.ejb.Ejb3Configuration. Това означава, че JVM може да намери този клас, но вече е опитал и не успя да зареди този клас.

Това е текстът Could not initialize class ..., който показва, че това се е случило. Ако JVM изобщо не можеше да намери класа, вместо това ще получите нещо като следното:

java.lang.NoClassDefFoundError: org/hibernate/ejb/Ejb3Configuration

Настрана, това също означава, че използвате Java 6 - в Java 5 съответното изключение няма съобщение.

Следващите два класа предоставят демонстрация на това поведение. Класът Unloadable не може да бъде зареден, защото неговият статичен инициализатор винаги хвърля изключение. Опитваме се да заредим този клас, хващаме резултата ExceptionInInitializerError и се опитваме да заредим Unloadable отново.

class Unloadable {
    static {
        if (true) { throw new RuntimeException(); }
    }
}

public class LoadingTest {
    public static void main(String[] args) throws Exception {
        try {
            Class.forName("Unloadable");
        }
        catch (ExceptionInInitializerError e) {
            try {
                Class.forName("Unloadable");
            }
            catch (NoClassDefFoundError e2) {
                System.out.println("XXXXXXXXXXXXXXXXXXXXX");
                e2.printStackTrace(System.out);
            }
        }
    }
}

Когато стартирам клас LoadingTest, получавам следния изход:

XXXXXXXXXXXXXXXXXXXXX
java.lang.NoClassDefFoundError: Could not initialize class Unloadable
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:169)
        at LoadingTest.main(LoadingTest.java:14)

Не мога да кажа какво причинява неуспех на първоначалния опит за зареждане на org.hibernate.ejb.Ejb3Configuration. Възможно е самият Ejb3Configuration да зависи от класове, които липсват в classpath. Може би си струва да прегледате списъка с всички класове, imported от Ejb3Configuration и гарантиране, че всички онези, които не са под java.* или javax.*, са в JAR, който Glassfish и Netbeans могат да видят.

Освен това мога само да предполагам защо JVM се опитва да зареди Ejb3Configuration два пъти. Когато зареждането на класа е неуспешно за първи път, се хвърля изключение (обикновено някакъв подклас на LinkageError). Този тип изключения не се улавят често, така че най-доброто ми предположение е, че се случва нещо като следното:

try {
    // Some code that loads Ejb3Configuration and fails.
}
finally {
    // Some code that also loads Ejb3Configuration and fails.
}

Ако кодът в блока finally хвърли изключение, това изключение ще замени всяко изключение, хвърлено в блока try. Предлагам това, защото подобно нещо се случи с този въпрос. Проследяването на стека, публикувано в този въпрос, идва от блок finally.

Ако отговорът ми все още не ви помогне, можете ли да публикувате цялата трасировка на стека, която виждате?

person Luke Woodward    schedule 22.05.2009
comment
Изглежда, че наистина е в конфигурацията на Log4J, която не се споменава в проследяването на стека, освен когато сървърът се рестартира за първи път. - person Jeff Ferland; 26.05.2009

Аз също имах този проблем, въпреки че изглежда, че в моя случай това е специфичен проблем за версията. По-новите версии на hibernate зависят от Simple Logging Facade за Java (SLF4J), но артефактите на maven включват само API, така че имате нужда от библиотеките за изпълнение във вашия WAR или в папката lib на сървъра.

Това е специфично за версия 3.4.0 на Hibernate Entity Manager, въпреки че може да се отнася и за други версии. Ако използвате Hibernate Core 3.3.x, вие сте на серията 3.4.x на Hibernate EM, така че имате НУЖДА от тези библиотеки за изпълнение.

person SplinterReality    schedule 06.08.2009