我尝试在我的网络应用程序中安装hbase / hadoop驱动程序为provided
。
此过程在Websphere中使用"共享库"引用,所以这似乎是特定于tomcat的。 Tomcat 8.0.x和8.5.x,Java 8.
来自pom.xml
:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-common</artifactId>
<version>1.1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
</dependency>
一个类在静态初始值设定项中初始化hbase对象:
public class SimpleServlet extends HttpServlet {
static {
ClassLoader classLoader = SimpleServlet.class.getClassLoader();
URL[] urLs = ((URLClassLoader) classLoader).getURLs();
LOGGER.info("SimpleServlet.class: " + Arrays.asList(urLs));
while(classLoader.getParent() != null) {
classLoader = classLoader.getParent();
urLs = ((URLClassLoader) classLoader).getURLs();
LOGGER.info("parent: " + Arrays.asList(urLs));
}
classLoader = Thread.currentThread().getContextClassLoader();
urLs = ((URLClassLoader) classLoader).getURLs();
LOGGER.info("context: " + Arrays.asList(urLs));
while(classLoader.getParent() != null) {
classLoader = classLoader.getParent();
urLs = ((URLClassLoader) classLoader).getURLs();
LOGGER.info("parent: " + Arrays.asList(urLs));
}
}
private static Configuration hbaseConfig = HBaseConfiguration.create();
...
}
我提供的代码已安装在the usual way:
中$ ls -l ../tomcat/8.5.8/libexec/lib/
...
-rw-r--r-- 1 ... 3429485 Aug 13 14:54 hadoop-common-2.7.1.jar
-rw-r--r-- 1 ... 530078 Aug 13 14:55 hbase-common-1.1.2.jar
-rw-r--r-- 1 ... 61829 Aug 13 14:56 commons-logging-1.2.jar
战争看起来像预期的那样:
$ jar tf .../target/sandbox-1.0-SNAPSHOT.war
META-INF/
META-INF/MANIFEST.MF
WEB-INF/
WEB-INF/classes/
WEB-INF/classes/com/
WEB-INF/classes/com/example/
WEB-INF/classes/webapp/
WEB-INF/classes/webapp/WEB-INF/
WEB-INF/lib/
WEB-INF/classes/com/example/SimpleServlet.class
WEB-INF/lib/guava-14.0.1.jar // <-- here it is
WEB-INF/web.xml
...
hbase静态方法在内部的某个构造函数中使用guava,并且Web应用程序在部署时失败:
13-Aug-2017 20:19:37.680 SEVERE [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.loadOnStartup Servlet [simpleServlet] in web application [] threw load() exception
java.lang.ClassNotFoundException: com.google.common.base.Preconditions
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.apache.hadoop.conf.Configuration$DeprecationDelta.<init>(Configuration.java:328)
at org.apache.hadoop.conf.Configuration$DeprecationDelta.<init>(Configuration.java:341)
at org.apache.hadoop.conf.Configuration.<clinit>(Configuration.java:423)
at com.example.SimpleServlet.<clinit>(SimpleServlet.java:20)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:119)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1050)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:989)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4913)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5223)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:752)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:728)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1702)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:482)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:431)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:324)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
如果将guava添加到共享libs目录,则提供的依赖项会看到它。
guava位于静态方法之前的静态初始化程序中的类路径输出上,共享库在父项中可见,如预期的那样:
[RMI TCP Connection(2)-127.0.0.1] INFO com.example.SimpleServlet - SimpleServlet.class: [file:.../webapps/ROOT/WEB-INF/classes/, file:.../webapps/ROOT/WEB-INF/lib/guava-14.0.1.jar, ...]
[RMI TCP Connection(2)-127.0.0.1] INFO com.example.SimpleServlet - parent: [..., .../lib/commons-logging-1.2.jar, .../lib/hadoop-common-2.7.1.jar, .../lib/hbase-common-1.1.2.jar, ...], ...
[RMI TCP Connection(2)-127.0.0.1] INFO com.example.SimpleServlet - context: [file:.../webapps/ROOT/WEB-INF/classes/, file:.../webapps/ROOT/WEB-INF/lib/guava-14.0.1.jar, ...]
[RMI TCP Connection(2)-127.0.0.1] INFO com.example.SimpleServlet - parent: [..., .../lib/commons-logging-1.2.jar, .../lib/hadoop-common-2.7.1.jar, .../lib/hbase-common-1.1.2.jar, ...], ...
为什么guava对提供的依赖项不可见?