0

この問題は、解決するのが非常に難しいことがわかっています。通常の話では、単体テストがなく、Antを使用して構築されたlibディレクトリにバージョン情報がダンプされていないさまざまな古いjar依存関係がなく、メンテナンスが非常に不十分なJavaWebアプリケーションを継承しました。依存関係のメンテナンスと理解を深めるために、Mavenに移行しました。その後、Springのバージョンがかなり古いことに気付きました(Spring2.xおよびSpringSecurity 2.0.3)。Spring2.5に正常にアップグレードしました。Springを3.1.2.RELEASEに、SpringSecurityを3.1.3.RELEASEに移行し始めました。

すべてがコンパイルされ、名前空間の問題も発生しません(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>        

他のすべてのSpringConfigファイルは、構成で次の名前空間ヘッダーを使用します。

<?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 Security2.0.4クラスorg.springframework.security.AuthenticationがSpring3.1クラスorg.springframework.beans.factory.support.AbstractAutowireCapableBeanFactoryによってどのように要求されるのでしょうか(Springセキュリティ設定とは関係ありません)。 )。DAOが(Spring依存性注入コンテナを介して)クラスローダーによってapplicationContext.xmlでインスタンス化される最初のBeanであるために選択された可能性がありますが、このアプリケーションのどこかにまだ参照が潜んでいることがわかりません。古い2.0.4クラス。すべてが正常にコンパイルされ、Maven pomは3.1のみを参照しているので、私の考えでは、古いクラスをプルしようとしている構成がどこかにあるはずです。Spring Securityの知識(特に大きなアプリをバージョン2からバージョン3にアップグレードする)を知っている人は、以前にこの問題に遭遇したことがあるかもしれませんが、Googleで完全に一致するものを見つけることができませんでした。これに関する提案をありがとう。現在困惑しています。

クイックアップデート:

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ディレクトリにある唯一のSpringjar(確かにgreped)は次のとおりです。

./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

繰り返しますが、賢明に見えます。

「認証」のソースコードを取得しても効果はありませんでした。これは、推移的なランタイム依存関係の問題のように見えます。コンパイル時に気付かれず、第1レベルの依存関係としてどこにも宣言されません。しかし、実行時に(Tomcat 6コンテナで)何らかの形でデプロイされると、古いライブラリファイルへの不正な参照が要求されます。

念のため、Tomcatインスタンスを削除し、最初からやり直します。

4

1 に答える 1

2

さて、ついにこの特定の問題を解決しました。NoClassDefFoundErrorは、まさにそれが缶に言っていることです。ルーク・テイラーが「あなたは絶対に再コンパイルしたのですか?」と尋ねたように。ええ、はい、いいえ。私は間違いなくターゲットを再コンパイルし、クリーンアップしました(Mavenを使用)。そして、逆コンパイラーを使用して生成されたクラス「XXXDao」のソースを初めて確認したとき、変更を確認しました。しかし、Javaソースから数行を追加/削除したときに、スタックトレースのエラーが同じ(ランダムな)行番号のままであることに気づきました。それは私がどういうわけか古い.classファイルを取得していたことを説明しました。結局のところ、Mavenおよび/またはEclipse(m2eclipseプラグイン)はどういうわけかクラスファイルを私のコアプロジェクト(ターゲットではない)のWEB-INF / classesディレクトリにコンパイルし、ターゲットのWEB-INF/classesディレクトリを非決定的に上書きしていましたいくつかのクラス。さらに見知らぬ人、クラスを.WARに圧縮するときは、常に古いクラスをデプロイしました。したがって、展開されたコンテンツは正しく見えるが、実際には異なるクラスの圧縮されたWARファイルの場合があります。

教訓-この種の動作が得られた場合は、コンパイル手順を再確認し、古いクラスファイル(古いAuthenticationクラスを参照)が新しいビルドにどのように組み込まれているかを調べてみてください。投稿に貢献してくれた人たちからのポインタをありがとう!

于 2013-03-06T03:31:50.613 に答える