这个问题很难解决。通常的故事,继承了一个维护得很差的java Web应用程序,没有单元测试和各种古老的jar依赖关系,在使用Ant构建的lib目录中没有转储版本信息。为了更好地维护和理解我迁移到Maven的依赖项。随后,我意识到Spring的版本已经很老了(Spring 2.x和Spring Security 2.0.3)。我成功升级到Spring 2.5。我现在已经开始将Spring迁移到3.1.2.RELEASE,并将Spring Security迁移到3.1.3.RELEASE。
Everything编译,我也没有得到任何命名空间问题(在Spring XML配置的头文件中声明),但在作为WAR文件部署到Tomcat容器时失败。日志文件报告:
Could not instantiate bean class [com.mydomain.repository.ReportDaoImpl]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/security/Authentication
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:997)
我查了一下,org.springframework.security.Authentication属于旧的Spring Security jar(2.0.4)
我目前的Maven依赖关系如下:
<spring.version>3.1.2.RELEASE</spring.version>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- SPRING SECURITY -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
我的security.xml很小:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http auto-config='true'>
<intercept-url pattern="/**" access="ROLE_Admin" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="password" authorities="ROLE_Admin" />
</user-service>
</authentication-provider>
</authentication-manager>
我的所有其他Spring Config文件在其配置中使用以下命名空间标题:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
据我所知,这个应用程序包含没有关于Spring的注释。
那么在实例化DAO对象时,如何通过Spring 3.1类org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory请求Spring Security 2.0.4类org.springframework.security.Authentication(与此无关) Spring安全设置)。可能是选择DAO是因为它是第一个bean,以便通过类加载器(通过Spring依赖注入容器)在applicationContext.xml中实例化,但是我无法看到在这个应用程序中某个地方仍然存在一个潜在的引用一个旧的2.0.4课程。因为一切都编译好了,而且Maven pom只引用了3.1,我认为必须有一些配置仍然试图引入一个旧类。任何具有Spring Security知识的人(特别是将大型应用程序从版本2升级到版本3)可能之前遇到过这个问题,但我无法通过谷歌找到完全匹配。感谢您对此提出的任何建议。目前难倒。
快速更新:
applicationContext.xml具有上面给出的命名空间标题,DAO简单地引用如下:
<bean id="reportDao" class="com.mydomain.repository.ReportDaoImpl">
<property name="dataSource" ref="myDataSource" />
</bean>
真的没有什么了。 applicationContext引入另一个上下文文件applicationContext-datasource,它声明了(与上面相同的名称空间标题):
<bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
</bean>
<bean id="myDataSource" parent="parentDataSource">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
ReportDao是超过1500行写得不好的程序代码。它是一个POJO并实现了rg.springframework.context.ApplicationContextAware。它还使用org.springframework.jdbc.core.support.JdbcDaoSupport对数据库执行CRUD操作。
运行mvn -X依赖项的输出(已切换到Spring [main] 3.0.7):
org.springframework:spring-webmvc:jar:3.0.7.RELEASE:compile
org.springframework:spring-asm:jar:3.0.7.RELEASE:compile
org.springframework:spring-beans:jar:3.0.7.RELEASE:compile
org.springframework:spring-expression:jar:3.0.7.RELEASE:compile
org.springframework:spring-web:jar:3.0.7.RELEASE:compile
org.springframework:spring-aop:jar:3.0.7.RELEASE:compile
aopalliance:aopalliance:jar:1.0:compile
org.springframework:spring-context:jar:3.0.7.RELEASE:compile
org.springframework:spring-context-support:jar:3.0.7.RELEASE:compile
org.springframework:spring-core:jar:3.0.7.RELEASE:compile
org.springframework:spring-tx:jar:3.0.7.RELEASE:compile
org.springframework:spring-jdbc:jar:3.0.7.RELEASE:compile
org.springframework.security:spring-security-acl:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-config:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-core:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-taglibs:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-web:jar:3.1.3.RELEASE:compile
org.springframework.security:spring-security-crypto:jar:3.1.3.RELEASE:compile
我相信看起来不错。
可交付WAR文件的WEB-INF / lib目录中唯一的spring jar(grepped to certain)是:
./spring-aop-3.0.7.RELEASE.jar
./spring-asm-3.0.7.RELEASE.jar
./spring-beans-3.0.7.RELEASE.jar
./spring-context-3.0.7.RELEASE.jar
./spring-context-support-3.0.7.RELEASE.jar
./spring-core-3.0.7.RELEASE.jar
./spring-expression-3.0.7.RELEASE.jar
./spring-jdbc-3.0.7.RELEASE.jar
./spring-security-acl-3.1.3.RELEASE.jar
./spring-security-config-3.1.3.RELEASE.jar
./spring-security-core-3.1.3.RELEASE.jar
./spring-security-crypto-3.1.3.RELEASE.jar
./spring-security-taglibs-3.1.3.RELEASE.jar
./spring-security-web-3.1.3.RELEASE.jar
./spring-tx-3.0.7.RELEASE.jar
./spring-web-3.0.7.RELEASE.jar
./spring-webmvc-3.0.7.RELEASE.jar
再一次,看起来很明智。
点击“身份验证”的源代码没有帮助。这看起来像传递运行时依赖性问题。它在编译时不会被注意到,并且不会在任何地方声明为第一级依赖项。但是在运行时(在Tomcat 6容器中)以某种方式部署了对旧库文件的恶意引用。
要删除我的Tomcat实例,并从头开始作为预防措施。
答案 0 :(得分:2)
好的,终于解决了这个特殊的问题。 NoClassDefFoundError正如它在锡上所说的那样。卢克泰勒问道:“你确定你重新编译了吗?”嗯,是的,不。我绝对重新编译,清理目标(使用Maven)等。第一次使用反编译器查看生成的类“XXXDao”的源代码时,我看到了我的更改。但我也注意到,当我从java源中添加/删除几行时,堆栈跟踪中的错误仍保留在相同(随机)行号上。这说明我得到了一个陈旧的.class文件。事实证明,Maven和/或Eclipse(m2eclipse插件)以某种方式设法将类文件编译到我的核心项目(而不是目标)的WEB-INF / classes目录中,并且无法确定地覆盖目标中的WEB-INF / classes目录一些课程。更奇怪的是,它总是在将类压缩为.WAR时部署旧类。所以你有一个爆炸内容看起来正确的情况,但实际上压缩的WAR文件有不同的类。
获得的经验 - 如果您遇到这种行为,请仔细检查编译步骤,并尝试找出旧类文件(引用旧的Authentication类)可能如何进入新构建。感谢那些为帖子做出贡献的指针!