我有一个由maven管理的项目,我有以下依赖
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-core</artifactId>
<version>1.1.3.2</version>
</dependency>
请注意,这个hadoop不是来自官方maven存储库,它是由我公司的团队生成的。
当我将项目部署到tomcat时,在tomcat启动时生成异常:
15/01/02 12:17:08 ERROR servlet.DispatcherServlet: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation. RequestMappingHandlerAdapter#0': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]: Constructor threw exception; nested exception is java.lang. NoSuchMethodError: org.codehaus.jackson.type.JavaType.<init>(Ljava/lang/Class;)V
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1011)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:957)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:490)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:598)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:517)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:458)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:138)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1197)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5229)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5516)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1575)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1565)
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:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.servlet.mvc.method.annotation. RequestMappingHandlerAdapter]: Constructor threw exception; nested exception is java.lang.NoSuchMethodError: org.codehaus.jackson.type.JavaType.<init>(Ljava/ lang/Class;)V
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
但是如果我从依赖中删除hadoop-core,那就再好了。所以我解压缩了hadoop-core.jar,发现内容如下:
$ ls
about.html gson-1.4.jar jdiff NOTICE slf4j-api-1.6.1.jar
asm-license.txt guava-11.0.2.jar jdtCompilerAdapter.jar objenesis-license.txt slf4j-simple-1.6.1.jar
bin.tgz hadoop-default.xml jsr305-1.3.9.jar org src
cglib-license.txt hadoop-metrics.properties junit org_apache_hadoop_conf_AutoDoc.properties stylesheet.css
client.login.conf hamcrest-license.txt junit3.8.1 org_apache_hadoop_conf_AutoDoc_zh_CN.properties tasks.properties
com hsqlServlet.class LICENSE overview.html webapps
COPYING images LICENSE.txt plugin.properties xml-apis-1.0.b2.jar
COPYRIGHT jar log4j.properties plugin.xml
digesterRules.xml javassist me properties.dtd
dom4j-1.6.1.jar javassist-3.16.1-GA.jar META-INF PropertyList-1.0.dtd
eu javax net README
$ ls org/codehaus/jackson/
annotate JsonFactory.class JsonParseException.class JsonToken.class schema Versioned.class
Base64Variant.class JsonGenerationException.class JsonParser.class map SerializableString.class
Base64Variants.class JsonGenerator.class JsonParser$Feature.class node sym
impl JsonGenerator$Feature.class JsonParser$NumberType.class ObjectCodec.class type
io JsonLocation.class JsonProcessingException.class package-info.class util
JsonEncoding.class JsonNode.class JsonStreamContext.class PrettyPrinter.class Version.class
所以我认为这是因为hadoop-core引入的jackson与当前不一致,我通过以下方式配置了shade插件:
<build>
...........
<plugins>
............
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>org.apache.hadoop:hadoop-core</artifact>
<includes>
<include>org/apache/hadoop/**</include>
</includes>
<excludes>
<exclude>org/codehaus/jackson/**</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
但它仍然不起作用,同样的例外仍然存在。为了确认类org.codehaus.jackson.type.JavaType的来源,我添加了以下代码:
System.out.println("-------loading WebController-------");
ProtectionDomain pd = org.codehaus.jackson.type.JavaType.class.getProtectionDomain();
CodeSource cs = pd.getCodeSource();
System.out.println(cs.getLocation());
pd = org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.class.getProtectionDomain();
cs = pd.getCodeSource();
System.out.println(cs.getLocation());
结果是:
-------loading WebController-------
file:/path/to/project/target/WEB-INF/lib/hadoop-core-1.1.3.2.jar
file:/path/to/project/target/WEB-INF/lib/spring-webmvc-3.2.0.RELEASE.jar
最后,我真的很困惑。顺便说一句,tomcat的配置是这样的:
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/path/to/the/target/path/generated/by/maven/projectname" debug="0" reloadable="false" crossContext="true" allowLinking="true"/>
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>