Почему CXF 2.7.5 (для jax-rs)/Spring 3.x/Hibernate 4.x приводит к java.lang.ClassNotFoundException: org.springframework.asm.ClassVisitor?

Я создаю службу RESTful через CXF 2.7.5 и использую подход cxf-servlet. javax-servlet 3.0 API, Spring 3.x и Hibernate 4.x — все это часть общей картины.

Прежде чем включать Spring JPA, Spring ORM и Hibernate в мой файл Maven POM, я мог создать файл войны, который фактически обслуживал четко определенную конечную точку (установленную через JAX-RS).

В любом случае теперь war-файл не развертывается в Tomcat 7.x; вместо этого возникает исключение, показанное в заголовке:

    java.lang.ClassNotFoundException: org.springframework.asm.ClassVisitor

Некоторые вещи, которые я уже проверил:

  • Tomcat 7.x работает с API-интерфейсами, совместимыми с javax-servlet 3.x.
  • Пакет с ClassVisitor (org.springframework.asm) однозначно указан среди jar-файлов в WEB-INF/lib. На самом деле, теперь он загружается как часть spring-core.

Я просмотрел ряд статей, объясняющих подобные обстоятельства. Но большинство в конечном итоге предлагают очевидное: убедитесь, что ClassVisitor упоминается в пути к классам.

Я перечисляю свой файл POM (по модулю нескольких исключений вверху), вместе с дескриптором развертывания web.xml для файла войны и applicationContext.xml. Внизу я также повторно перечислил исключение с контекстом.

maven 3.x POM:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.acme.etorf</groupId>
  <artifactId>etorf</artifactId>
  ...
  <version>1</version>
  <packaging>war</packaging>

  <properties>
    <cxf.version>2.7.5</cxf.version>
    <spring.version>3.2.2.RELEASE</spring.version>
    <spring.asm.version>3.1.4.RELEASE</spring.asm.version>
    <spring.jpa.version>2.0.8</spring.jpa.version>
    <hibernate.version>4.2.2.Final</hibernate.version>
    <hibernate.jpa.api.version>2.0-cr-1</hibernate.jpa.api.version>
    <mysql.connector.version>5.1.25</mysql.connector.version>
    <c3p0.version>0.9.1.2</c3p0.version>
    <slf4j.version>1.7.5</slf4j.version>
  </properties>

  <build>
    <pluginManagement>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugin</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
              <source>1.6</source>
              <target>1.6</target>
            </configuration>
          </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>2.1</version>
          <configuration>
            <webXml>WebContent/WEB-INF/web.xml</webXml>
          </configuration>
        </plugin>
        </plugins>
      </pluginManagement>
  </build>

  <dependencies>
        <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
        </dependency>

    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
      <version>${cxf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http</artifactId>
      <version>${cxf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http-hc</artifactId>
      <version>${cxf.version}</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</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-orm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jpa</artifactId>
      <version>${spring.jpa.version}</version>
      <exclusions>
        <exclusion>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>${mysql.connector.version}</version>
        </dependency>
        <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>${hibernate.version}</version>
        </dependency>

    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>${c3p0.version}</version>
    </dependency>

        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>${slf4j.version}</version>
        </dependency>
  </dependencies>
</project>

веб.xml:

<web-app
  version="3.0"
  xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name>etorf</display-name>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

  <servlet>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
  </servlet>

  <servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

  <session-config>
    <session-timeout>60</session-timeout>
  </session-config>
</web-app>

приложениеContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements. See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership. The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License. You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied. See the License for the
  specific language governing permissions and limitations
  under the License.
-->
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jaxrs="http://cxf.apache.org/jaxrs"
  xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
                      http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://cxf.apache.org/jaxrs
                      http://cxf.apache.org/schemas/jaxrs.xsd
                      http://cxf.apache.org/transports/http/configuration
                      http://cxf.apache.org/schemas/configuration/http-conf.xsd
                                            http://www.springframework.org/schema/tx
                                            http://www.springframework.org/schema/tx/spring-tx.xsd">

  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="location">
        <value>classpath:hibernate.properties</value>
      </property>
    </bean>

  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${hibernate.connection.driver_class}" />
    <property name="jdbcUrl" value="${hibernate.connection.url}" />
    <property name="user" value="${hibernate.connection.username}" />
    <property name="password" value="${hibernate.connection.password}" />
    <property name="acquireIncrement" value="5" />
    <property name="minPoolSize" value="5" />
    <property name="maxPoolSize" value="150" />
    <property name="maxIdleTime" value="1800" />
  </bean>

  <bean id="hibernateJpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
  <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="database" value="MYSQL" />
    <!-- <property name="showSql" value="true" /> -->
    <!--<property name="generateDdl" value="true" /> -->
  </bean>

  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />

    <property name="persistenceXmlLocation" value="classpath:persistence.xml" />
    <property name="persistenceUnitName" value="Forte-Persistence-Unit" />
    <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />

    <property name="jpaPropertyMap">
      <map>
        <entry key="hibernate.transaction.flush_before_completion" value="true" />
        <entry key="hibernate.transaction.auto_close_session" value="true" />
        <entry key="hibernate.current_session_context_class" value="jta" />
        <entry key="hibernate.connection.release_mode" value="auto" />
        <!-- <entry key="hibernate.show_sql" value="true" />-->
      </map>
    </property>

    <property name="jpaDialect" ref="hibernateJpaDialect" />
  </bean>

  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
  </bean>
  <tx:annotation-driven transaction-manager="transactionManager" />

  <bean id="helloservice" class="com.kornferry.service.HelloServiceImpl"/>
  <jaxrs:server id="helloworld" address="/">
    <jaxrs:serviceBeans>
      <ref bean="helloservice"/>
    </jaxrs:serviceBeans>                  
  </jaxrs:server>

</beans>

Исключение из catalina.out:

INFO: Refreshing Root WebApplicationContext: startup date [Mon Jul 08 22:47:52 PDT 2013]; root of context hierarchy
Jul 8, 2013 10:47:52 PM org.springframework.web.context.ContextLoader initWebApplicationContext
SEVERE: Context initialization failed
java.lang.NoClassDefFoundError: org/springframework/asm/ClassVisitor
        at org.springframework.context.support.AbstractRefreshableApplicationContext.customizeBeanFactory(AbstractRefreshableApplicationContext.java:218)
        at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129)
        at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:467)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:397)
        at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:282)
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:204)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4887)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5381)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:976)
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1653)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
        at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.ClassNotFoundException: org.springframework.asm.ClassVisitor
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
        ... 21 more
Jul 8, 2013 10:47:52 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart
Jul 8, 2013 10:47:52 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/cxf-library] startup failed due to previous errors

person Kode Charlie    schedule 09.07.2013    source источник
comment
ClassVisitor находится внутри spring-asm-3.x.jar. Вы уверены, что поняли? Похоже, у вас конфликт в зависимостях/библиотеках. Проверьте версии. Я полагаю, вы не используете maven?   -  person willome    schedule 09.07.2013
comment
org.springframework.asm (включая ClassVisitor) также теперь находится внутри spring-core-3.2.2.RELEASE.jar. Список зависимостей maven показывает, что spring-core загружается как побочный эффект загрузки spring-tx: [INFO] +- org.springframework:spring-tx:jar:3.2.2.RELEASE:compile [INFO] | +- aopalliance:aopalliance:jar:1.0:compile [INFO] | +- org.springframework:spring-beans:jar:3.2.2.RELEASE:compile [INFO] | \- org.springframework:spring-core:jar:3.2.2.RELEASE:compile   -  person Kode Charlie    schedule 09.07.2013
comment
каков результат зависимости mvn -o: список   -  person willome    schedule 09.07.2013
comment
Я решил проблему: spring-asm был в пути к классам моего военного файла. Однако в Tomcat/webapps был еще один военный файл, для которого не был определен spring-asm! Итак, исключения в конце концов не срабатывали для моего файла войны. Эта проблема почти такая же, как: stackoverflow.com/questions/9268101/   -  person Kode Charlie    schedule 09.07.2013


Ответы (1)


Смотрите мой последний комментарий. Отсутствующее исключение ClassVisitor было вызвано cxf-library.war, отдельным военным файлом от моего собственного. После удаления cxf-libray.war (и его распакованной папки), а затем перезапуска Tomcat исключение исчезло.

person Kode Charlie    schedule 09.07.2013