java - requiere - Problema con el error NoClassDefFoundError en un entorno web Spring/Wicket/Derby/Jetty
se necesita jre (4)
Intento crear una aplicación de plantilla de Spring de JDBC, el framework web que estoy usando es wicket y está en el servidor web de jetty 6 (a través del Plugin de Jetty Maven). Además, estoy compilando la aplicación con Eclipse.
Por algún motivo, obtengo un NoClassDefFoundError con la clase Derby jdbc. Estoy asumiendo que obtendría una clase no encontrada. No se encontró una excepción, así que supongo que algo más está sucediendo. La clase derby es parte del classpath, el directorio WEB-INF / lib. ¿Cuál crees que es el problema?
Mi opinión sobre el problema: No es un error de "jar no encontrado en classpath", sino más bien un problema con Java o Spring cargando dinámicamente esa clase y cuándo se carga.
Estoy usando Eclipse como herramienta de desarrollo, pero probablemente no sea parte del problema. Todavía estoy usando Maven en la línea de comando y obteniendo el mismo problema.
Aquí está el error:
WicketMessage: no se puede crear una instancia de la página con el constructor public wicketspring.easy.HomePage ()
Causa principal:
java.lang.NoClassDefFoundError: Could not initialize class org.apache.derby.jdbc.EmbeddedDriver
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1130)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:113)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:577)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:619)
at wicketspring.easy.jdbc.JdbcWicketSpringHandler.data(JdbcWicketSpringHandler.java:39)
at WICKET_wicketspring.easy.jdbc.JdbcWicketSpringHandler$$FastClassByCGLIB$$f1187cb6.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.apache.wicket.proxy.LazyInitProxyFactory$CGLibInterceptor.intercept(LazyInitProxyFactory.java:319)
at WICKET_wicketspring.easy.jdbc.JdbcWicketSpringHandler$$EnhancerByCGLIB$$e8f0e174.data(<generated>)
at wicketspring.easy.HomePage.<init>(HomePage.java:91)
at wicketspring.easy.HomePage.<init>(HomePage.java:47)
Aquí está la applicationContext.xml para Spring:
<beans>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="url"><value>jdbc:derby:wicketspringdb</value></property>
<property name="username"><value></value></property>
<property name="password"><value></value></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
<beans>
<import resource="classpath:common.xml"/>
<bean id="jdbcHandler" class=wicketspring.easy.jdbc.JdbcWicketSpringHandler">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
</beans>
...
Another stack trace system out.
Page.java:74) - At [2b] -- java.lang.NoClassDefFoundError: Could not initialize class org.apache.derby.jdbc.EmbeddedDriver
java.lang.NoClassDefFoundError: Could not initialize class org.apache.derby.jdbc.EmbeddedDriver
at wicketspring.easy.HomePage.<init>(HomePage.java:72)
at wicketspring.easy.HomePage.<init>(HomePage.java:47)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:
39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorIm
pl.java:27)
...
Aquí está el código de Java, el código se compila y puedo imprimir la clase, pero no puedo crear una instancia. ¿Extraño?
Código de Java:
package wicketspring.easy;
import java.util.List;
import org.apache.wicket.Application;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.proxy.IProxyTargetLocator;
import org.apache.wicket.proxy.LazyInitProxyFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import model.LoadableDetachableList;
import model.SelectionOptionBean;
import wicketspring.easy.jdbc.JdbcWicketSpringHandler;
import wicketspring.easy.service.IStateListService;
import wicketspring.easy.service.StateListServiceImpl;
import org.apache.derby.jdbc.EmbeddedDriver;
public class HomePage extends WebPage {
private final JdbcWicketSpringHandler jdbcWicketSpringHandler;
public HomePage(final PageParameters parameters) {
super(parameters);
jdbcWicketSpringHandler = (JdbcWicketSpringHandler) LazyInitProxyFactory.createProxy(JdbcWicketSpringHandler.class,
new IProxyTargetLocator() {
private static final long serialVersionUID = 1L;
public Object locateProxyTarget() {
return ((WicketApplication) Application.get()).context().getBean("jdbcHandler");
}
});
/// WEIRD BECAUSE IT REACHES THIS POINT!!!
LOGGER.debug("At [1] -- " + EmbeddedDriver.class);
try {
LOGGER.debug("At [2] -- " + new org.apache.derby.jdbc.EmbeddedDriver());
} catch (NoClassDefFoundError ne) {
// STACK TRACE ERROR HERE!!!!
LOGGER.debug("At [2b] -- " + ne);
ne.printStackTrace();
} catch (Exception e) {
LOGGER.debug("At [2] -- " + e);
e.printStackTrace();
}
try {
LOGGER.debug("At -- " + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"));
} catch (NoClassDefFoundError ne) {
LOGGER.debug("At [3b] -- " + ne);
ne.printStackTrace();
} catch (Exception e) {
LOGGER.debug("At [3] -- " + e);
e.printStackTrace();
}
/// ERROR FOR STACKOVERFLOW IS GENERATED FROM THIS LINE!!!!
LOGGER.debug("At HomePage - jdbcHandler [3]: " + jdbcWicketSpringHandler.toStringJdbcTemplate());
LOGGER.debug("At HomePage - jdbcHandler [3]: " + jdbcWicketSpringHandler.data());
...
} // End of Class //
Editar: me puede estar faltando un archivo jar que es una dependencia de Spring Jdbc o dbcp.
Aquí está mi listado de WEB-INF / lib:
antlr-2.7.6.jar
aopalliance-1.0.jar
avalon-framework-4.1.3.jar
axis-1.4.jar
axis-jaxrpc-1.4.jar
cglib-nodep-2.2.jar
commons-collections-3.1.jar
commons-dbcp-1.2.2.jar
commons-logging-1.1.jar
commons-pool-1.3.jar
derby-10.6.1.0.jar
dom4j-1.6.1.jar
hibernate-core-3.5.1-Final.jar
jetty-6.1.4.jar
jetty-management-6.1.4.jar
jetty-util-6.1.4.jar
jta-1.1.jar
log4j-1.2.14.jar
logkit-1.0.1.jar
mx4j-3.0.1.jar
mx4j-tools-3.0.1.jar
servlet-api-2.5-6.1.4.jar
servlet-api-2.5.jar
slf4j-api-1.5.8.jar
slf4j-log4j12-1.4.2.jar
spring-2.5.6.jar
spring-aop-2.5.6.jar
spring-beans-2.5.6.jar
spring-context-2.5.6.jar
spring-core-2.5.6.jar
spring-jdbc-2.5.6.jar
spring-test-2.5.6.jar
spring-tx-2.5.6.jar
testRunWrapper-1.0.0.jar
wicket-1.4.13.jar
wicket-ioc-1.4.13.jar
wicket-spring-1.4.13.jar
xml-apis-1.0.b2.jar
¿Estás seguro de que tu derby.jar contiene la clase org.apache.derby.jdbc.EmbeddedDriver
? Es posible que desee comprobar que tiene la versión correcta.
Si está utilizando Maven para empaquetar la aplicación, es extraño que el nombre del derby.jar
termine siendo derby.jar
sin ningún número de versión.
A veces estos errores se deben a que tienes Derby en tu classpath dos veces, de alguna manera. Con los JDK modernos, los controladores de Derby se ''autocargan'', lo que significa que el JDK buscará los controladores JDBC en el classpath y los cargará automáticamente. Por lo tanto, puede consultar el classpath de su sistema y las bibliotecas de su aplicación; quizás tengas una segunda copia de Derby escondida en algún lugar del camino y la excepción es intentar decirte que las dos versiones de Derby están en conflicto.
El mensaje Could not initialize class org.apache.derby.jdbc.EmbeddedDriver
significa que, en ese momento, la JVM ya intentó y no pudo inicializar esta clase.
La JVM no podrá inicializar una clase si se lanza una excepción y no se captura dentro del inicializador estático de la clase. Las únicas razones por las que la JVM intentaría inicializar la clase EmbeddedDriver más de una vez serían:
- se produjo una excepción al inicializar la clase, esta excepción se descubrió en otra parte y el programa continuó,
- se lanzó una excepción al inicializar la clase, pero el programa entró en un bloque
finally
, y dentro de este bloquefinally
, la JVM intentó cargar la clase nuevamente.
El inicializador estático para EmbeddedDriver ( fuente ) llama a un método de boot()
. Sin embargo, este método de boot()
llama a un poco de otro código, por lo que es difícil saber dónde podría estar el problema. Eché un vistazo a algunos de los orígenes de org.apache.commons.dbcp.BasicDataSource
, pero parece que los números de línea en su stacktrace no concuerdan con la fuente. No sé qué versión de commons-dbcp está usando.
Si no tiene otros mensajes de salida ni stacktraces para continuar, su mejor opción puede ser conectar la fuente de Derby a su depurador y recorrerlo para ver qué está sucediendo.
Por otro lado, es muy posible "imprimir" una clase que no se ha inicializado. Considere las siguientes clases:class St1 {
static {
System.out.println("In static initializer");
}
}
public class St2 {
public static void main(String[] args) {
System.out.println(St1.class);
System.out.println(new St1());
}
}
Cuando ejecuto la clase St2
, obtengo el siguiente resultado:
class St1 In static initializer St1@65690726
Por lo tanto, el error "No se pudo inicializar la clase org.apache.derby.jdbc.EmbeddedDriver" fue en realidad el síntoma principal de algunos otros problemas de carga de clases menos obvios.
Estaba usando Jetty como servidor web y Spring como el framework bajo java6.
Creo que hubo un problema de carga de clases, relacionado con la clase MBeanServer.
E ignoré un error que ocurrió al inicio: "Causado por: java.lang.LinkageError: violación de la restricción del cargador: cargador (instancia de org / mortbay / jetty / webapp / WebAppClassLoader) carga iniciada anteriormente para un tipo diferente con el nombre" javax / management / MBeanServer "en java.lang.ClassLoader.defineClass1 (método nativo) en java.lang.ClassLoader.defineClassCond (ClassLoader.java:632) en java.lang.ClassLoader.defineClass (ClassLoader.java:616) en java. security.SecureClassLoader.defineClass (SecureClassLoader.java:141) "
Busqué la clase en mi directorio WEB-INF / lib. Fue incluido como parte de mx4j: jar. Mx4j era una dependencia de jetty-management.jar. Realmente no necesitaba administración de embarcadero, así que eliminé esa referencia de mi archivo pom.
Básicamente, la inclusión de MBeanServer (de mx4j) causó algún tipo de problema de carga de clase donde org.apache.derby.jdbc.EmbeddedDriver no se pudo cargar correctamente. Lo eliminé de mi aplicación web y la aplicación comenzó a funcionar correctamente.